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 alloc+xfunc: xmalloc, then xfunc - leaks memory if xfunc dies open+xfunc: opens fd, then calls xfunc - fd is leaked if xfunc dies leaks: does not free allocated memory or opened fds 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 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 would make 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 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". [ - NOFORK [[ - NOFORK acpid - daemon add-shell addgroup adduser adjtimex ar - runner arch - NOFORK arp - complex, rare arping - runner ash - interactive, longterm awk - noexec. runner base64 - runner basename - NOFORK beep blkdiscard blkid blockdev bootchartd - daemon brctl bunzip2 - runner busybox bzcat - runner bzip2 - runner cal - runner: cal -n9999 cat - runner chat - needs ^C to work chattr - runner chgrp - noexec. runner chmod - noexec. runner chown - noexec. runner chpasswd - runner (list of "user:password"s from stdin) chpst - spawner chroot - spawner chrt - spawner chvt - leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds. Also, "rare" category. Can be noexec. cksum - noexec. runner clear - NOFORK cmp - runner comm - runner conspy - interactive cp - noexec. runner cpio - runner crond - daemon crontab cryptpw - changes state: with --password-fd=N, moves N to stdin. Also, "rare" category. Can be noexec. cttyhack - spawner cut - noexec. runner date - noexec. nofork candidate(needs to stop messing up env, free xasprintf result, not use xfuncs after xasprintf) dc - runner (eats stdin if no params) dd - noexec. runner deallocvt - leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds. Also, "rare" category. Can be noexec. delgroup deluser depmod - complex, rare devmem - runner, complex (access to device memory may hang) df - complex (nested allocs) dhcprelay - daemon diff - runner dirname - NOFORK dmesg - runner dnsd - daemon dnsdomainname - needs ^C (may talk to DNS servers, which may be down) dos2unix - noexec. runner dpkg - runner du - runner dumpkmap - leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds. Also, "rare" category. Can be noexec. dumpleases echo - NOFORK ed - interactive, longterm egrep - longterm runner ("CMD | egrep ..." may run indefinitely, better to exec to conserve memory) eject - leaks: open+ioctl_or_perror_and_die, changes state (moves fds) env - noexec. changes state (env) envdir - spawner envuidgid - spawner expand - runner expr - complex (nested allocs) factor - runner (eats stdin if no params) fakeidentd - daemon false - NOFORK fatattr - complex (xopen+xioctl can leak fd) fbset - leaks: open+xfunc, complex, rare fbsplash - runner, longterm fdflush - leaks: open+ioctl_or_perror_and_die, needs ^C (floppy may be unresponsive), rare fdformat - needs ^C (floppy may be unresponsive), longterm, rare fdisk - interactive, longterm fgconsole - leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds. Also, "rare" category. Can be noexec. fgrep - longterm runner ("CMD | fgrep ..." may run indefinitely, better to exec to conserve memory) find - noexec. runner findfs - suid flash_eraseall flash_lock flash_unlock flashcp flock - spawner, changes state (file locks) fold - noexec. runner free - nofork candidate(struct globals, needs to close /proc/meminfo fd) freeramdisk - leaks: open+ioctl_or_perror_and_die fsck - interactive, longterm fsck.minix fsfreeze fstrim fsync - NOFORK ftpd - daemon ftpget - runner ftpput - runner fuser - complex getopt - noexec. complex (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 - complex, rare head - noexec. runner hexdump - noexec. runner hostid - NOFORK hostname - DNS resolution may trigger, need ^C httpd - daemon hush - interactive, longterm hwclock i2cdetect i2cdump i2cget i2cset id - noexec ifconfig ifenslave ifplugd - daemon inetd - daemon init - daemon inotifyd - daemon insmod - noexec install - runner ionice - spawner iostat - runner ip - noexec candidate ipaddr - noexec candidate ipcalc - noexec candidate ipcrm - noexec candidate ipcs - noexec candidate iplink - noexec candidate ipneigh - noexec candidate iproute - noexec candidate iprule - noexec candidate iptunnel - noexec candidate kbd_mode 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 - spawner linux64 - spawner linuxrc - daemon ln - noexec loadfont loadkmap - leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds. Also, "rare" category. Can be noexec. logger - runner login - suid, interactive, longterm logname - NOFORK losetup - complex lpd - daemon lpq - runner lpr - runner ls - noexec. runner lsattr - runner. noexec candidate (ls is, why not this one?) lsmod - noexec lsof - complex lspci - noexec candidate, too rare to bother for nofork lsscsi - noexec candidate, too rare to bother for nofork lsusb - noexec candidate, too rare to bother for nofork lzcat - runner lzma - runner lzop - runner lzopcat - runner makedevs makemime - runner man - spawner, interactive, longterm md5sum - noexec. runner mdev - daemon mesg microcom - interactive, longterm mkdir - NOFORK mkdosfs mke2fs mkfifo - noexec mkfs.ext2 mkfs.minix mkfs.vfat mknod - noexec mkpasswd mkswap mktemp - noexec. leaks: xstrdup+concat_path_file modinfo - noexec modprobe - noexec more - interactive, longterm mount - suid mountpoint mpstat mt mv - runner (can be noexec?) nameif nbd-client nc - runner netstat - runner with -c nice - spawner nl - runner nmeter - runner nohup - spawner nproc - NOFORK ntpd - daemon od - runner openvt - spawner partprobe passwd - suid paste - noexec. runner patch pgrep - nofork candidate(xregcomp, procps_scan - are they ok?) pidof - nofork candidate(uses find_pid_by_name, is that ok?) ping - suid, runner ping6 - suid, runner pipe_progress pivot_root pkill - nofork candidate(xregcomp, procps_scan - are they ok?) pmap popmaildir - runner poweroff - rare powertop - interactive, longterm printenv - NOFORK printf - NOFORK ps - noexec candidate pscan - longterm pstree pwd - NOFORK pwdx - NOFORK raidautorun rdate rdev readlink - NOFORK readprofile realpath - NOFORK reboot - rare reformime - runner remove-shell renice - nofork candidate(uses getpwnam, is that ok?) reset - spawner (execs "stty") resize - noexec. changes state (signal handlers) rev - runner rm - noexec. rm -i interactive rmdir - NOFORK rmmod - noexec route rpm - runner rpm2cpio - runner rtcwake - complex, rare run-parts runlevel runsv - daemon runsvdir - daemon rx - runner script scriptreplay sed - runner sendmail - runner seq - noexec. runner setarch - spawner setconsole setfont setkeycodes setlogcons setpriv - spawner setserial setsid - spawner setuidgid sha1sum - noexec. runner sha256sum - noexec. runner sha3sum - noexec. runner sha512sum - noexec. runner showkey - interactive, longterm shred - runner shuf - noexec. runner slattach sleep - runner smemcap - runner softlimit - spawner sort - noexec. runner split - runner ssl_client - network start-stop-daemon stat - nofork candidate(needs fewer allocs) strings - runner stty su - suid, spawner sulogin - spawner sum - runner sv svc svlogd - daemon swapoff - rare swapon - rare switch_root - spawner, rare, changes state sync - NOFORK sysctl syslogd - daemon tac - noexec. runner tail - runner tar - runner taskset - spawner tcpsvd - daemon tee - runner telnet - interactive, longterm telnetd - daemon test - NOFORK tftp - runner tftpd - daemon time - spawner, changes state (signals) timeout - spawner, changes state (signals) top - interactive, longterm touch - NOFORK tr - runner traceroute - suid, runner traceroute6 - suid, runner true - NOFORK truncate - NOFORK tty - NOFORK ttysize - NOFORK tunctl tune2fs - leaks: open+xfunc ubiattach ubidetach ubimkvol ubirename ubirmvol ubirsvol ubiupdatevol udhcpc - daemon udhcpd - daemon udpsvd - daemon uevent - daemon umount uname - NOFORK uncompress - runner unexpand - runner uniq - runner unix2dos - noexec. runner unlink - NOFORK unlzma - runner unlzop - runner unxz - runner unzip - runner uptime - nofork candidate(is getutxent ok?) users - nofork candidate(is getutxent ok?) usleep - NOFORK uudecode - runner uuencode - runner vconfig - leaks: xsocket+ioctl_or_perror_and_die vi - interactive, longterm vlock - suid volname - runner w wall - suid watch - runner watchdog - daemon wc - runner wget - runner which - NOFORK who whoami - NOFORK whois xargs - noexec. spawner xxd - noexec. runner xz - runner xzcat - runner yes - noexec. runner zcat - runner zcip - daemon