1Why an applet can't be NOFORK or NOEXEC?
   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)
  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.
  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)
  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
  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".
  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).
  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