1Why an applet can't be NOFORK or NOEXEC? 2 3Why can't be NOFORK: 4interactive: may wait for user input, ^C has to work 5spawner: "tool PROG ARGS" which changes program state and execs - must fork 6changes state: e.g. environment, signal handlers 7leaks: does not free allocated memory or opened fds 8 alloc+xfunc: xmalloc, then xfunc - leaks memory if xfunc dies 9 open+xfunc: opens fd, then calls xfunc - fd is leaked if xfunc dies 10talks to network/serial/etc: it's not known how long the delay can be, 11 it's reasonable to expect it might be many seconds 12 (even if usually it is not), so ^C has to work 13runner: sometimes may run for long(ish) time, and/or works with network: 14 ^C has to work (cat BIGFILE, chmod -R, ftpget, nc) 15 16"runners" can become eligible after shell is taught ^C to interrupt NOFORKs, 17need to be inspected that they do not fall into alloc+xfunc, open+xfunc, 18leak categories. 19 20Why can't be NOEXEC: 21suid: runs under different uid - must fork+exec 22if it's important that /proc/PID/cmdline and comm are correct. 23 ("pkill sh" killing itself before it kills real "sh" is no fun) 24 25Why shouldn't be NOFORK/NOEXEC: 26rare: not started often enough to bother optimizing (example: poweroff) 27daemon: runs indefinitely; these are also always fit "rare" category 28longterm: often runs for a long time (many seconds), execing makes 29 memory footprint smaller 30complex: no immediately obvious reason why NOFORK wouldn't work, 31 but does some non-obvoius operations (example: fuser, lsof, losetup); 32 detailed audit often turns out that it's a leaker 33hardware: performs unusual hardware ops which may take long, 34 or even hang due to hardware or firmware bugs 35 36Interesting example of "interactive" applet which is nevertheless can be 37(and is) NOEXEC is "rm". Yes, "rm -i" is interactive - but it's not that typical 38for users to keep it waiting for many minutes, whereas running "rm" in shell 39is very typical, and speeding up this common use via NOEXEC is useful. 40IOW: rm is "interactive", but not "longterm". 41 42Interesting example of an applet which can be NOFORK but if not, 43then should not be NOEXEC, is "usleep". As NOFORK, it amount to simply 44nanosleep()ing in the calling program (usually shell). No memory wasted. 45But if ran as NOEXEC, it would create a potentially long-term process, 46which would be taking more memory because it did not exec 47and did not free much of the copied memory of the parent 48(COW helps with this only as long as parent doesn't modify its memory). 49 50 51[ - NOFORK 52[[ - NOFORK 53acpid - daemon 54add-shell - noexec. leaks: open+xfunc 55addgroup - noexec. leaks 56adduser - noexec. leaks 57adjtimex - NOFORK 58ar - runner 59arch - NOFORK 60arp - talks to network: arp -n queries DNS 61arping - longterm 62ash - interactive, longterm 63awk - noexec. runner 64base64 - runner 65basename - NOFORK 66beep - longterm: beep -r 999999999 67blkdiscard - noexec. leaks: open+xioctl 68blkid - noexec 69blockdev - noexec. leaks fd 70bootchartd - daemon 71brctl - noexec 72bunzip2 - runner 73bzcat - runner 74bzip2 - runner 75cal - noexec. can be runner: cal -n9999 76cat - runner: cat HUGEFILE 77chat - longterm (when used as intended - talking to modem over stdin/out) 78chattr - noexec. runner 79chgrp - noexec. runner 80chmod - noexec. runner 81chown - noexec. runner 82chpasswd - longterm? (list of "user:password"s from stdin) 83chpst - noexec. spawner 84chroot - noexec. spawner 85chrt - noexec. spawner 86chvt - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds 87cksum - noexec. runner 88clear - NOFORK 89cmp - runner 90comm - runner 91conspy - interactive, longterm 92cp - noexec. sometimes runner 93cpio - runner 94crond - daemon 95crontab - longterm (runs $EDITOR), leaks: open+xasprintf 96cryptpw - noexec. changes state: with --password-fd=N, moves N to stdin 97cttyhack - noexec. spawner 98cut - noexec. runner 99date - noexec. nofork candidate(needs to stop messing up env, free xasprintf result, not use xfuncs after xasprintf) 100dc - longterm (eats stdin if no params) 101dd - noexec. runner 102deallocvt - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds 103delgroup - noexec. leaks 104deluser - noexec. leaks 105depmod - longterm(ish) 106devmem - hardware (access to device memory may hang) 107df - noexec. leaks: nested allocs 108dhcprelay - daemon 109diff - runner 110dirname - NOFORK 111dmesg - runner 112dnsd - daemon 113dnsdomainname - noexec. talks to network (may query DNS) 114dos2unix - noexec. runner 115dpkg - runner 116du - runner 117dumpkmap - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds 118dumpleases - noexec. leaks: open+xread 119echo - NOFORK 120ed - interactive, longterm 121egrep - longterm runner ("CMD | egrep ..." may run indefinitely, better to exec to conserve memory) 122eject - hardware, leaks: open+ioctl_or_perror_and_die, changes state (moves fds) 123env - noexec. spawner, changes state (env) 124envdir - noexec. spawner 125envuidgid - noexec. spawner 126expand - runner 127expr - noexec. leaks: nested allocs 128factor - longterm (eats stdin if no params) 129fakeidentd - daemon 130false - NOFORK 131fatattr - noexec. leaks: open+xioctl, complex 132fbset - hardware, leaks: open+xfunc 133fbsplash - runner, longterm 134fdflush - hardware, leaks: open+ioctl_or_perror_and_die 135fdformat - hardware, longterm 136fdisk - interactive, longterm 137fgconsole - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds 138fgrep - longterm runner ("CMD | fgrep ..." may run indefinitely, better to exec to conserve memory) 139find - noexec. runner 140findfs - suid 141flash_eraseall - hardware 142flash_lock - hardware 143flash_unlock - hardware 144flashcp - hardware 145flock - spawner, changes state (file locks), let's play safe and not be noexec 146fold - noexec. runner 147free - NOFORK 148freeramdisk - noexec. leaks: open+ioctl_or_perror_and_die 149fsck - interactive, longterm 150fsck.minix - needs ^C 151fsfreeze - noexec. leaks: open+xioctl 152fstrim - noexec. leaks: open+xioctl, find_block_device -> readdir+xstrdup 153fsync - NOFORK 154ftpd - daemon 155ftpget - runner 156ftpput - runner 157fuser - complex 158getopt - noexec. leaks: many allocs 159getty - interactive, longterm 160grep - longterm runner ("CMD | grep ..." may run indefinitely, better to exec to conserve memory) 161groups - noexec 162gunzip - runner 163gzip - runner 164halt - rare 165hd - noexec. runner 166hdparm - hardware 167head - noexec. runner 168hexdump - noexec. runner 169hexedit - interactive, longterm 170hostid - NOFORK 171hostname - noexec. talks to network (hostname -d may query DNS) 172httpd - daemon 173hush - interactive, longterm 174hwclock - hardware (xioctl(RTC_RD_TIME)) 175i2cdetect - hardware 176i2cdump - hardware 177i2cget - hardware 178i2cset - hardware 179id - noexec 180ifconfig - hardware? (mem_start NN io_addr NN irq NN), leaks: xsocket+ioctl_or_perror_and_die 181ifenslave - noexec. leaks: xsocket+bb_perror_msg_and_die 182ifplugd - daemon 183inetd - daemon 184init - daemon 185inotifyd - daemon 186insmod - noexec 187install - runner 188ionice - noexec. spawner 189iostat - longterm: "iostat 1" runs indefinitely 190ip - noexec 191ipaddr - noexec 192ipcalc - noexec. ipcalc -h talks to network 193ipcrm - noexec 194ipcs - noexec 195iplink - noexec 196ipneigh - noexec 197iproute - noexec 198iprule - noexec 199iptunnel - noexec 200kbd_mode - noexec. leaks: xopen_nonblocking+xioctl 201kill - NOFORK 202killall - NOFORK 203killall5 - NOFORK 204klogd - daemon 205last - runner (I've got 1300 lines of output when tried it) 206less - interactive, longterm 207link - NOFORK 208linux32 - noexec. spawner 209linux64 - noexec. spawner 210linuxrc - daemon 211ln - noexec 212loadfont - noexec. leaks: config_open+bb_error_msg_and_die("map format") 213loadkmap - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds 214logger - runner 215login - suid, interactive, longterm 216logname - NOFORK 217losetup - noexec. complex 218lpd - daemon 219lpq - runner 220lpr - runner 221ls - noexec. runner 222lsattr - noexec. runner 223lsmod - noexec 224lsof - complex 225lspci - noexec. too rare to bother for nofork 226lsscsi - noexec. too rare to bother for nofork 227lsusb - noexec. too rare to bother for nofork 228lzcat - runner 229lzma - runner 230lzop - runner 231lzopcat - runner 232makedevs - noexec 233makemime - runner 234man - spawner, interactive, longterm 235md5sum - noexec. runner 236mdev - daemon 237mesg - NOFORK 238microcom - interactive, longterm 239minips - noexec 240mkdir - NOFORK 241mkdosfs - needs ^C 242mke2fs - needs ^C 243mkfifo - noexec 244mkfs.ext2 - needs ^C 245mkfs.minix - needs ^C 246mkfs.vfat - needs ^C 247mknod - noexec 248mkpasswd - noexec. changes state: with --password-fd=N, moves N to stdin 249mkswap - needs ^C 250mktemp - noexec. leaks: xstrdup+concat_path_file 251modinfo - noexec 252modprobe - noexec 253more - interactive, longterm 254mount - suid 255mountpoint - noexec. leaks: option -n "print dev name": find_block_device -> readdir+xstrdup 256mpstat - longterm: "mpstat 1" runs indefinitely 257mt - hardware 258mv - noexec. sometimes runner 259nameif - noexec. openlog(), leaks: config_open2+ioctl_or_perror_and_die 260nbd-client - noexec 261nc - runner 262netstat - longterm with -c (continuous listing) 263nice - noexec. spawner 264nl - runner 265nmeter - longterm 266nohup - noexec. spawner 267nproc - NOFORK 268ntpd - daemon 269nuke - noexec 270od - runner 271openvt - longterm: spawns a child and waits for it 272partprobe - noexec. leaks: open+ioctl_or_perror_and_die(BLKRRPART) 273passwd - suid 274paste - noexec. runner 275patch - needs ^C 276pgrep - must fork+exec to get correct /proc/PID/cmdline and comm field 277pidof - must fork+exec to get correct /proc/PID/cmdline and comm field 278ping - suid, longterm 279ping6 - suid, longterm 280pipe_progress - longterm 281pivot_root - NOFORK 282pkill - must fork+exec to get correct /proc/PID/cmdline and comm field 283pmap - noexec candidate, leaks: open+xstrdup 284popmaildir - runner 285poweroff - rare 286powertop - interactive, longterm 287printenv - NOFORK 288printf - NOFORK 289ps - noexec 290pscan - talks to network 291pstree - noexec 292pwd - NOFORK 293pwdx - NOFORK 294raidautorun - noexec. very simple. leaks: open+xioctl 295rdate - talks to network 296rdev - noexec. leaks: find_block_device -> readdir+xstrdup 297readlink - NOFORK 298readprofile - reads /boot/System.map and /proc/profile, better to free more memory by execing? 299realpath - NOFORK 300reboot - rare 301reformime - runner 302remove-shell - noexec. leaks: open+xfunc 303renice - noexec. nofork candidate(uses getpwnam, is that ok?) 304reset - noexec. spawner (execs "stty") 305resize - noexec. changes state (signal handlers) 306resume - noexec 307rev - runner 308rm - noexec. rm -i interactive 309rmdir - NOFORK 310rmmod - noexec 311route - talks to network (may query DNS to convert IPs to names) 312rpm - runner 313rpm2cpio - runner 314rtcwake - longterm: puts system to sleep, optimizing this for speed is pointless 315run-init - spawner, rare, changes state (oh yes), execing may be important to free binary's inode 316run-parts - longterm 317runlevel - noexec. can be nofork if "endutxent()" is called unconditionally, but too rare to bother? 318runsv - daemon 319runsvdir - daemon 320rx - runner 321script - longterm: pumps script output from slave pty 322scriptreplay - longterm: plays back "script" saved output, sleeping as necessary. 323sed - runner 324sendmail - runner 325seq - noexec. runner 326setarch - noexec. spawner 327setconsole - noexec 328setfattr - noexec 329setfont - noexec. leaks a lot of stuff 330setkeycodes - noexec 331setlogcons - noexec 332setpriv - spawner, changes state, let's play safe and not be noexec 333setserial - noexec 334setsid - spawner, uses fork_or_rexec() [not audited to work in noexec], let's play safe and not be noexec 335setuidgid - noexec. spawner 336sha1sum - noexec. runner 337sha256sum - noexec. runner 338sha3sum - noexec. runner 339sha512sum - noexec. runner 340showkey - interactive, longterm 341shred - runner 342shuf - noexec. runner 343slattach - longterm (may sleep forever), uses bb_common_bufsiz1 344sleep - longterm. Could be nofork, if not the problem of "killall sleep" not killing it. 345smemcap - runner 346softlimit - noexec. spawner 347sort - noexec. runner 348split - runner 349ssl_client - longterm 350start-stop-daemon - not noexec: uses bb_common_bufsiz1 351stat - noexec. nofork candidate(needs fewer allocs) 352strings - runner 353stty - 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 354su - suid, spawner 355sulogin - noexec. spawner 356sum - runner 357sv - noexec. needs ^C (uses usleep(420000)) 358svc - noexec. needs ^C (uses usleep(420000)) 359svlogd - daemon 360swapoff - longterm: may cause memory pressure, execing is beneficial 361swapon - rare 362switch_root - spawner, rare, changes state (oh yes), execing may be important to free binary's inode 363sync - NOFORK 364sysctl - noexec. leaks: xstrdup+xmalloc_read 365syslogd - daemon 366tac - noexec. runner 367tail - runner 368tar - runner 369taskset - noexec. spawner 370tcpsvd - daemon 371tee - runner 372telnet - interactive, longterm 373telnetd - daemon 374test - NOFORK 375tftp - runner 376tftpd - daemon 377time - spawner, longterm, changes state (signals) 378timeout - spawner, longterm, changes state (signals) 379top - interactive, longterm 380touch - NOFORK 381tr - runner 382traceroute - suid, longterm 383traceroute6 - suid, longterm 384true - NOFORK 385truncate - NOFORK 386tty - NOFORK 387ttysize - NOFORK 388tunctl - noexec 389tune2fs - noexec. leaks: open+xfunc 390ubiattach - hardware 391ubidetach - hardware 392ubimkvol - hardware 393ubirename - hardware 394ubirmvol - hardware 395ubirsvol - hardware 396ubiupdatevol - hardware 397udhcpc - daemon 398udhcpd - daemon 399udpsvd - daemon 400uevent - daemon 401umount - noexec. leaks: nested xmalloc 402uname - NOFORK 403uncompress - runner 404unexpand - runner 405uniq - runner 406unix2dos - noexec. runner 407unlink - NOFORK 408unlzma - runner 409unlzop - runner 410unxz - runner 411unzip - runner 412uptime - noexec. nofork candidate(is getutxent ok?) 413users - noexec. nofork candidate(is getutxent ok?) 414usleep - NOFORK. But what about "killall usleep"? 415uudecode - runner 416uuencode - runner 417vconfig - noexec. leaks: xsocket+ioctl_or_perror_and_die 418vi - interactive, longterm 419vlock - suid 420volname - hardware (reads CDROM, this can take long-ish if need to spin up) 421w - noexec. nofork candidate(is getutxent ok?) 422wall - suid 423watch - longterm 424watchdog - daemon 425wc - runner 426wget - longterm 427which - NOFORK 428who - noexec. nofork candidate(is getutxent ok?) 429whoami - NOFORK 430whois - talks to network 431xargs - noexec. spawner 432xxd - noexec. runner 433xz - runner 434xzcat - runner 435yes - noexec. runner 436zcat - runner 437zcip - daemon 438