123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- 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 - 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. 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 candidate, 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
|