438 lines
14 KiB
Plaintext
438 lines
14 KiB
Plaintext
Why an applet can't be NOFORK or NOEXEC?
|
|
|
|
Why can't be NOFORK:
|
|
interactive: may wait for user input, ^C has to work
|
|
spawner: "tool PROG ARGS" which changes program state and execs - must fork
|
|
changes state: e.g. environment, signal handlers
|
|
leaks: does not free allocated memory or opened fds
|
|
alloc+xfunc: xmalloc, then xfunc - leaks memory if xfunc dies
|
|
open+xfunc: opens fd, then calls xfunc - fd is leaked if xfunc dies
|
|
talks to network/serial/etc: it's not known how long the delay can be,
|
|
it's reasonable to expect it might be many seconds
|
|
(even if usually it is not), so ^C has to work
|
|
runner: sometimes may run for long(ish) time, and/or works with network:
|
|
^C has to work (cat BIGFILE, chmod -R, ftpget, nc)
|
|
|
|
"runners" can become eligible after shell is taught ^C to interrupt NOFORKs,
|
|
need to be inspected that they do not fall into alloc+xfunc, open+xfunc,
|
|
leak categories.
|
|
|
|
Why can't be NOEXEC:
|
|
suid: runs under different uid - must fork+exec
|
|
if it's important that /proc/PID/cmdline and comm are correct.
|
|
("pkill sh" killing itself before it kills real "sh" is no fun)
|
|
|
|
Why shouldn't be NOFORK/NOEXEC:
|
|
rare: not started often enough to bother optimizing (example: poweroff)
|
|
daemon: runs indefinitely; these are also always fit "rare" category
|
|
longterm: often runs for a long time (many seconds), execing makes
|
|
memory footprint smaller
|
|
complex: no immediately obvious reason why NOFORK wouldn't work,
|
|
but does some non-obvoius operations (example: fuser, lsof, losetup);
|
|
detailed audit often turns out that it's a leaker
|
|
hardware: performs unusual hardware ops which may take long,
|
|
or even hang due to hardware or firmware bugs
|
|
|
|
Interesting example of "interactive" applet which is nevertheless can be
|
|
(and is) NOEXEC is "rm". Yes, "rm -i" is interactive - but it's not that typical
|
|
for users to keep it waiting for many minutes, whereas running "rm" in shell
|
|
is very typical, and speeding up this common use via NOEXEC is useful.
|
|
IOW: rm is "interactive", but not "longterm".
|
|
|
|
Interesting example of an applet which can be NOFORK but if not,
|
|
then should not be NOEXEC, is "usleep". As NOFORK, it amount to simply
|
|
nanosleep()ing in the calling program (usually shell). No memory wasted.
|
|
But if ran as NOEXEC, it would create a potentially long-term process,
|
|
which would be taking more memory because it did not exec
|
|
and did not free much of the copied memory of the parent
|
|
(COW helps with this only as long as parent doesn't modify its memory).
|
|
|
|
|
|
[ - NOFORK
|
|
[[ - NOFORK
|
|
acpid - daemon
|
|
add-shell - noexec. leaks: open+xfunc
|
|
addgroup - noexec. leaks
|
|
adduser - noexec. leaks
|
|
adjtimex - NOFORK
|
|
ar - runner
|
|
arch - NOFORK
|
|
arp - talks to network: arp -n queries DNS
|
|
arping - longterm
|
|
ash - interactive, longterm
|
|
awk - noexec. runner
|
|
base64 - runner
|
|
basename - NOFORK
|
|
beep - longterm: beep -r 999999999
|
|
blkdiscard - noexec. leaks: open+xioctl
|
|
blkid - noexec
|
|
blockdev - noexec. leaks fd
|
|
bootchartd - daemon
|
|
brctl - noexec
|
|
bunzip2 - runner
|
|
bzcat - runner
|
|
bzip2 - runner
|
|
cal - noexec. can be runner: cal -n9999
|
|
cat - runner: cat HUGEFILE
|
|
chat - longterm (when used as intended - talking to modem over stdin/out)
|
|
chattr - noexec. runner
|
|
chgrp - noexec. runner
|
|
chmod - noexec. runner
|
|
chown - noexec. runner
|
|
chpasswd - longterm? (list of "user:password"s from stdin)
|
|
chpst - noexec. spawner
|
|
chroot - noexec. spawner
|
|
chrt - noexec. spawner
|
|
chvt - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
|
|
cksum - noexec. runner
|
|
clear - NOFORK
|
|
cmp - runner
|
|
comm - runner
|
|
conspy - interactive, longterm
|
|
cp - noexec. sometimes runner
|
|
cpio - runner
|
|
crond - daemon
|
|
crontab - longterm (runs $EDITOR), leaks: open+xasprintf
|
|
cryptpw - noexec. changes state: with --password-fd=N, moves N to stdin
|
|
cttyhack - noexec. spawner
|
|
cut - noexec. runner
|
|
date - noexec. nofork candidate(needs to stop messing up env, free xasprintf result, not use xfuncs after xasprintf)
|
|
dc - longterm (eats stdin if no params)
|
|
dd - noexec. runner
|
|
deallocvt - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
|
|
delgroup - noexec. leaks
|
|
deluser - noexec. leaks
|
|
depmod - longterm(ish)
|
|
devmem - hardware (access to device memory may hang)
|
|
df - noexec. leaks: nested allocs
|
|
dhcprelay - daemon
|
|
diff - runner
|
|
dirname - NOFORK
|
|
dmesg - runner
|
|
dnsd - daemon
|
|
dnsdomainname - noexec. talks to network (may query DNS)
|
|
dos2unix - noexec. runner
|
|
dpkg - runner
|
|
du - runner
|
|
dumpkmap - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
|
|
dumpleases - noexec. leaks: open+xread
|
|
echo - NOFORK
|
|
ed - interactive, longterm
|
|
egrep - longterm runner ("CMD | egrep ..." may run indefinitely, better to exec to conserve memory)
|
|
eject - hardware, leaks: open+ioctl_or_perror_and_die, changes state (moves fds)
|
|
env - noexec. spawner, changes state (env)
|
|
envdir - noexec. spawner
|
|
envuidgid - noexec. spawner
|
|
expand - runner
|
|
expr - noexec. leaks: nested allocs
|
|
factor - longterm (eats stdin if no params)
|
|
fakeidentd - daemon
|
|
false - NOFORK
|
|
fatattr - noexec. leaks: open+xioctl, complex
|
|
fbset - hardware, leaks: open+xfunc
|
|
fbsplash - runner, longterm
|
|
fdflush - hardware, leaks: open+ioctl_or_perror_and_die
|
|
fdformat - hardware, longterm
|
|
fdisk - interactive, longterm
|
|
fgconsole - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
|
|
fgrep - longterm runner ("CMD | fgrep ..." may run indefinitely, better to exec to conserve memory)
|
|
find - noexec. runner
|
|
findfs - suid
|
|
flash_eraseall - hardware
|
|
flash_lock - hardware
|
|
flash_unlock - hardware
|
|
flashcp - hardware
|
|
flock - spawner, changes state (file locks), let's play safe and not be noexec
|
|
fold - noexec. runner
|
|
free - NOFORK
|
|
freeramdisk - noexec. leaks: open+ioctl_or_perror_and_die
|
|
fsck - interactive, longterm
|
|
fsck.minix - needs ^C
|
|
fsfreeze - noexec. leaks: open+xioctl
|
|
fstrim - noexec. leaks: open+xioctl, find_block_device -> readdir+xstrdup
|
|
fsync - NOFORK
|
|
ftpd - daemon
|
|
ftpget - runner
|
|
ftpput - runner
|
|
fuser - complex
|
|
getopt - noexec. leaks: many allocs
|
|
getty - interactive, longterm
|
|
grep - longterm runner ("CMD | grep ..." may run indefinitely, better to exec to conserve memory)
|
|
groups - noexec
|
|
gunzip - runner
|
|
gzip - runner
|
|
halt - rare
|
|
hd - noexec. runner
|
|
hdparm - hardware
|
|
head - noexec. runner
|
|
hexdump - noexec. runner
|
|
hexedit - interactive, longterm
|
|
hostid - NOFORK
|
|
hostname - noexec. talks to network (hostname -d may query DNS)
|
|
httpd - daemon
|
|
hush - interactive, longterm
|
|
hwclock - hardware (xioctl(RTC_RD_TIME))
|
|
i2cdetect - hardware
|
|
i2cdump - hardware
|
|
i2cget - hardware
|
|
i2cset - hardware
|
|
id - noexec
|
|
ifconfig - hardware? (mem_start NN io_addr NN irq NN), leaks: xsocket+ioctl_or_perror_and_die
|
|
ifenslave - noexec. leaks: xsocket+bb_perror_msg_and_die
|
|
ifplugd - daemon
|
|
inetd - daemon
|
|
init - daemon
|
|
inotifyd - daemon
|
|
insmod - noexec
|
|
install - runner
|
|
ionice - noexec. spawner
|
|
iostat - longterm: "iostat 1" runs indefinitely
|
|
ip - noexec
|
|
ipaddr - noexec
|
|
ipcalc - noexec. ipcalc -h talks to network
|
|
ipcrm - noexec
|
|
ipcs - noexec
|
|
iplink - noexec
|
|
ipneigh - noexec
|
|
iproute - noexec
|
|
iprule - noexec
|
|
iptunnel - noexec
|
|
kbd_mode - noexec. leaks: xopen_nonblocking+xioctl
|
|
kill - NOFORK
|
|
killall - NOFORK
|
|
killall5 - NOFORK
|
|
klogd - daemon
|
|
last - runner (I've got 1300 lines of output when tried it)
|
|
less - interactive, longterm
|
|
link - NOFORK
|
|
linux32 - noexec. spawner
|
|
linux64 - noexec. spawner
|
|
linuxrc - daemon
|
|
ln - noexec
|
|
loadfont - noexec. leaks: config_open+bb_error_msg_and_die("map format")
|
|
loadkmap - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
|
|
logger - runner
|
|
login - suid, interactive, longterm
|
|
logname - NOFORK
|
|
losetup - noexec. complex
|
|
lpd - daemon
|
|
lpq - runner
|
|
lpr - runner
|
|
ls - noexec. runner
|
|
lsattr - noexec. runner
|
|
lsmod - noexec
|
|
lsof - complex
|
|
lspci - noexec. too rare to bother for nofork
|
|
lsscsi - noexec. too rare to bother for nofork
|
|
lsusb - noexec. too rare to bother for nofork
|
|
lzcat - runner
|
|
lzma - runner
|
|
lzop - runner
|
|
lzopcat - runner
|
|
makedevs - noexec
|
|
makemime - runner
|
|
man - spawner, interactive, longterm
|
|
md5sum - noexec. runner
|
|
mdev - daemon
|
|
mesg - NOFORK
|
|
microcom - interactive, longterm
|
|
minips - noexec
|
|
mkdir - NOFORK
|
|
mkdosfs - needs ^C
|
|
mke2fs - needs ^C
|
|
mkfifo - noexec
|
|
mkfs.ext2 - needs ^C
|
|
mkfs.minix - needs ^C
|
|
mkfs.vfat - needs ^C
|
|
mknod - noexec
|
|
mkpasswd - noexec. changes state: with --password-fd=N, moves N to stdin
|
|
mkswap - needs ^C
|
|
mktemp - noexec. leaks: xstrdup+concat_path_file
|
|
modinfo - noexec
|
|
modprobe - noexec
|
|
more - interactive, longterm
|
|
mount - suid
|
|
mountpoint - noexec. leaks: option -n "print dev name": find_block_device -> readdir+xstrdup
|
|
mpstat - longterm: "mpstat 1" runs indefinitely
|
|
mt - hardware
|
|
mv - noexec. sometimes runner
|
|
nameif - noexec. openlog(), leaks: config_open2+ioctl_or_perror_and_die
|
|
nbd-client - noexec
|
|
nc - runner
|
|
netstat - longterm with -c (continuous listing)
|
|
nice - noexec. spawner
|
|
nl - runner
|
|
nmeter - longterm
|
|
nohup - noexec. spawner
|
|
nproc - NOFORK
|
|
ntpd - daemon
|
|
nuke - noexec
|
|
od - runner
|
|
openvt - longterm: spawns a child and waits for it
|
|
partprobe - noexec. leaks: open+ioctl_or_perror_and_die(BLKRRPART)
|
|
passwd - suid
|
|
paste - noexec. runner
|
|
patch - needs ^C
|
|
pgrep - must fork+exec to get correct /proc/PID/cmdline and comm field
|
|
pidof - must fork+exec to get correct /proc/PID/cmdline and comm field
|
|
ping - suid, longterm
|
|
ping6 - suid, longterm
|
|
pipe_progress - longterm
|
|
pivot_root - NOFORK
|
|
pkill - must fork+exec to get correct /proc/PID/cmdline and comm field
|
|
pmap - noexec candidate, leaks: open+xstrdup
|
|
popmaildir - runner
|
|
poweroff - rare
|
|
powertop - interactive, longterm
|
|
printenv - NOFORK
|
|
printf - NOFORK
|
|
ps - noexec
|
|
pscan - talks to network
|
|
pstree - noexec
|
|
pwd - NOFORK
|
|
pwdx - NOFORK
|
|
raidautorun - noexec. very simple. leaks: open+xioctl
|
|
rdate - talks to network
|
|
rdev - noexec. leaks: find_block_device -> readdir+xstrdup
|
|
readlink - NOFORK
|
|
readprofile - reads /boot/System.map and /proc/profile, better to free more memory by execing?
|
|
realpath - NOFORK
|
|
reboot - rare
|
|
reformime - runner
|
|
remove-shell - noexec. leaks: open+xfunc
|
|
renice - noexec. nofork candidate(uses getpwnam, is that ok?)
|
|
reset - noexec. spawner (execs "stty")
|
|
resize - noexec. changes state (signal handlers)
|
|
resume - noexec
|
|
rev - runner
|
|
rm - noexec. rm -i interactive
|
|
rmdir - NOFORK
|
|
rmmod - noexec
|
|
route - talks to network (may query DNS to convert IPs to names)
|
|
rpm - runner
|
|
rpm2cpio - runner
|
|
rtcwake - longterm: puts system to sleep, optimizing this for speed is pointless
|
|
run-init - spawner, rare, changes state (oh yes), execing may be important to free binary's inode
|
|
run-parts - longterm
|
|
runlevel - noexec. can be nofork if "endutxent()" is called unconditionally, but too rare to bother?
|
|
runsv - daemon
|
|
runsvdir - daemon
|
|
rx - runner
|
|
script - longterm: pumps script output from slave pty
|
|
scriptreplay - longterm: plays back "script" saved output, sleeping as necessary.
|
|
sed - runner
|
|
sendmail - runner
|
|
seq - noexec. runner
|
|
setarch - noexec. spawner
|
|
setconsole - noexec
|
|
setfattr - noexec
|
|
setfont - noexec. leaks a lot of stuff
|
|
setkeycodes - noexec
|
|
setlogcons - noexec
|
|
setpriv - spawner, changes state, let's play safe and not be noexec
|
|
setserial - noexec
|
|
setsid - spawner, uses fork_or_rexec() [not audited to work in noexec], let's play safe and not be noexec
|
|
setuidgid - noexec. spawner
|
|
sha1sum - noexec. runner
|
|
sha256sum - noexec. runner
|
|
sha3sum - noexec. runner
|
|
sha512sum - noexec. runner
|
|
showkey - interactive, longterm
|
|
shred - runner
|
|
shuf - noexec. runner
|
|
slattach - longterm (may sleep forever), uses bb_common_bufsiz1
|
|
sleep - longterm. Could be nofork, if not the problem of "killall sleep" not killing it.
|
|
smemcap - runner
|
|
softlimit - noexec. spawner
|
|
sort - noexec. runner
|
|
split - runner
|
|
ssl_client - longterm
|
|
start-stop-daemon - not noexec: uses bb_common_bufsiz1
|
|
stat - noexec. nofork candidate(needs fewer allocs)
|
|
strings - runner
|
|
stty - noexec. nofork candidate: has no allocs or opens except xmove_fd(xopen("-F DEVICE"),STDIN). tcsetattr(STDIN) is not a problem: it would work the same across processes sharing this fd
|
|
su - suid, spawner
|
|
sulogin - noexec. spawner
|
|
sum - runner
|
|
sv - noexec. needs ^C (uses usleep(420000))
|
|
svc - noexec. needs ^C (uses usleep(420000))
|
|
svlogd - daemon
|
|
swapoff - longterm: may cause memory pressure, execing is beneficial
|
|
swapon - rare
|
|
switch_root - spawner, rare, changes state (oh yes), execing may be important to free binary's inode
|
|
sync - NOFORK
|
|
sysctl - noexec. leaks: xstrdup+xmalloc_read
|
|
syslogd - daemon
|
|
tac - noexec. runner
|
|
tail - runner
|
|
tar - runner
|
|
taskset - noexec. spawner
|
|
tcpsvd - daemon
|
|
tee - runner
|
|
telnet - interactive, longterm
|
|
telnetd - daemon
|
|
test - NOFORK
|
|
tftp - runner
|
|
tftpd - daemon
|
|
time - spawner, longterm, changes state (signals)
|
|
timeout - spawner, longterm, changes state (signals)
|
|
top - interactive, longterm
|
|
touch - NOFORK
|
|
tr - runner
|
|
traceroute - suid, longterm
|
|
traceroute6 - suid, longterm
|
|
true - NOFORK
|
|
truncate - NOFORK
|
|
tty - NOFORK
|
|
ttysize - NOFORK
|
|
tunctl - noexec
|
|
tune2fs - noexec. leaks: open+xfunc
|
|
ubiattach - hardware
|
|
ubidetach - hardware
|
|
ubimkvol - hardware
|
|
ubirename - hardware
|
|
ubirmvol - hardware
|
|
ubirsvol - hardware
|
|
ubiupdatevol - hardware
|
|
udhcpc - daemon
|
|
udhcpd - daemon
|
|
udpsvd - daemon
|
|
uevent - daemon
|
|
umount - noexec. leaks: nested xmalloc
|
|
uname - NOFORK
|
|
uncompress - runner
|
|
unexpand - runner
|
|
uniq - runner
|
|
unix2dos - noexec. runner
|
|
unlink - NOFORK
|
|
unlzma - runner
|
|
unlzop - runner
|
|
unxz - runner
|
|
unzip - runner
|
|
uptime - noexec. nofork candidate(is getutxent ok?)
|
|
users - noexec. nofork candidate(is getutxent ok?)
|
|
usleep - NOFORK. But what about "killall usleep"?
|
|
uudecode - runner
|
|
uuencode - runner
|
|
vconfig - noexec. leaks: xsocket+ioctl_or_perror_and_die
|
|
vi - interactive, longterm
|
|
vlock - suid
|
|
volname - hardware (reads CDROM, this can take long-ish if need to spin up)
|
|
w - noexec. nofork candidate(is getutxent ok?)
|
|
wall - suid
|
|
watch - longterm
|
|
watchdog - daemon
|
|
wc - runner
|
|
wget - longterm
|
|
which - NOFORK
|
|
who - noexec. nofork candidate(is getutxent ok?)
|
|
whoami - NOFORK
|
|
whois - talks to network
|
|
xargs - noexec. spawner
|
|
xxd - noexec. runner
|
|
xz - runner
|
|
xzcat - runner
|
|
yes - noexec. runner
|
|
zcat - runner
|
|
zcip - daemon
|