| 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 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 |
| |
| 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 - noexec. leaks fd |
| bootchartd - daemon |
| brctl |
| bunzip2 - runner |
| busybox |
| bzcat - runner |
| bzip2 - runner |
| cal - runner: cal -n9999 |
| cat - runner |
| chat - needs ^C to work |
| chattr - noexec. runner |
| chgrp - noexec. runner |
| chmod - noexec. runner |
| chown - noexec. runner |
| chpasswd - runner (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 0 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 - runner (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 |
| deluser |
| depmod - complex, rare |
| devmem - runner, complex (access to device memory may hang) |
| df - leaks: 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 - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds |
| dumpleases - leaks: open+xread |
| 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. spawner, changes state (env) |
| envdir - noexec. spawner |
| envuidgid - noexec. spawner |
| expand - runner |
| expr - leaks: nested allocs |
| factor - runner (eats stdin if no params) |
| fakeidentd - daemon |
| false - NOFORK |
| fatattr - leaks: open+xioctl, complex |
| 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 - 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 |
| flash_lock |
| flash_unlock |
| flashcp |
| flock - spawner, changes state (file locks), let's play safe and not be noexec |
| 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 - 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 - complex, rare |
| head - noexec. runner |
| hexdump - noexec. runner |
| hostid - NOFORK |
| hostname - needs ^C (may talk to DNS servers, which may be down) |
| httpd - daemon |
| hush - interactive, longterm |
| hwclock - talks to hardware (xioctl(RTC_RD_TIME)) - needs ^C |
| i2cdetect |
| i2cdump |
| i2cget |
| i2cset |
| id - noexec |
| ifconfig - leaks: xsocket+ioctl_or_perror_and_die |
| ifenslave - leaks: xsocket+bb_perror_msg_and_die |
| ifplugd - daemon |
| inetd - daemon |
| init - daemon |
| inotifyd - daemon |
| insmod - noexec |
| install - runner |
| ionice - noexec. 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 - 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 - 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 - complex |
| lpd - daemon |
| lpq - runner |
| lpr - runner |
| ls - noexec. runner |
| lsattr - noexec. runner |
| 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 - NOFORK |
| microcom - interactive, longterm |
| 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 - noexec candidate (it's a measuring tool, putting less load by itself is good), complex |
| mt - rare |
| mv - noexec candidate, runner |
| nameif - leaks: config_open2+ioctl_or_perror_and_die |
| nbd-client |
| nc - runner |
| netstat - runner with -c |
| nice - noexec. spawner |
| nl - runner |
| nmeter - longterm |
| nohup - noexec. spawner |
| nproc - NOFORK |
| ntpd - daemon |
| 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 - 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 - longterm |
| pivot_root - NOFORK |
| pkill - nofork candidate(xregcomp, procps_scan - are they ok?) |
| pmap - noexec candidate, leaks: open+xstrdup |
| popmaildir - runner |
| poweroff - rare |
| powertop - interactive, longterm |
| printenv - NOFORK |
| printf - NOFORK |
| ps - looks for AT_CLKTCK elf aux vector, therefore can't be noexec |
| pscan - longterm |
| pstree - noexec |
| pwd - NOFORK |
| pwdx - NOFORK |
| raidautorun |
| rdate - needs ^C (may talk to DNS servers, which may be down) |
| rdev - leaks: find_block_device -> readdir+xstrdup |
| readlink - NOFORK |
| readprofile |
| realpath - NOFORK |
| reboot - rare |
| reformime - runner |
| remove-shell |
| renice - nofork candidate(uses getpwnam, is that ok?) |
| reset - noexec. spawner (execs "stty") |
| resize - noexec. changes state (signal handlers) |
| rev - runner |
| rm - noexec. rm -i interactive |
| rmdir - NOFORK |
| rmmod - noexec |
| route - needs ^C (may talk to DNS servers, which may be down) |
| rpm - runner |
| rpm2cpio - runner |
| rtcwake - longterm: puts system to sleep, optimizing this for speed is pointless |
| run-parts |
| runlevel - noexec. can be nofork if "endutxent()" is called unconditionally, but too rare to bother? |
| runsv - daemon |
| runsvdir - daemon |
| rx - runner |
| script |
| scriptreplay |
| sed - runner |
| sendmail - runner |
| seq - noexec. runner |
| setarch - noexec. spawner |
| setconsole |
| setfont |
| setkeycodes |
| setlogcons |
| setpriv - spawner, changes state, let's play safe and not be noexec |
| setserial |
| setsid - spawner, uses fork_or_rexec() [not audted 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 |
| sleep - runner, longterm |
| smemcap - runner |
| softlimit - noexec. spawner |
| sort - noexec. runner |
| split - runner |
| ssl_client - longterm |
| start-stop-daemon |
| stat - 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 - rare |
| 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, runner |
| traceroute6 - suid, runner |
| true - NOFORK |
| truncate - NOFORK |
| tty - NOFORK |
| ttysize - NOFORK |
| tunctl |
| tune2fs - noexec. leaks: open+xfunc |
| ubiattach |
| ubidetach |
| ubimkvol |
| ubirename |
| ubirmvol |
| ubirsvol |
| ubiupdatevol |
| udhcpc - daemon |
| udhcpd - daemon |
| udpsvd - daemon |
| uevent - daemon |
| umount - noexec candidate, 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 - 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 - nofork candidate(is getutxent ok?) |
| wall - suid |
| watch - longterm |
| watchdog - daemon |
| wc - runner |
| wget - longterm |
| which - NOFORK |
| who - nofork candidate(is getutxent ok?) |
| whoami - NOFORK |
| whois - needs ^C |
| xargs - noexec. spawner |
| xxd - noexec. runner |
| xz - runner |
| xzcat - runner |
| yes - noexec. runner |
| zcat - runner |
| zcip - daemon |