1 Why an applet can't be NOFORK or NOEXEC?
4 interactive: may wait for user input, ^C has to work
5 spawner: "tool PROG ARGS" which changes program state and execs - must fork
6 changes state: e.g. environment, signal handlers
7 leaks: 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
10 talks 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
13 runner: 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,
17 need to be inspected that they do not fall into alloc+xfunc, open+xfunc,
21 suid: runs under different uid - must fork+exec
22 if it's important that /proc/PID/cmdline and comm are correct.
23 ("pkill sh" killing itself before it kills real "sh" is no fun)
25 Why shouldn't be NOFORK/NOEXEC:
26 rare: not started often enough to bother optimizing (example: poweroff)
27 daemon: runs indefinitely; these are also always fit "rare" category
28 longterm: often runs for a long time (many seconds), execing makes
29 memory footprint smaller
30 complex: 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
33 hardware: performs unusual hardware ops which may take long,
34 or even hang due to hardware or firmware bugs
36 Interesting 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
38 for users to keep it waiting for many minutes, whereas running "rm" in shell
39 is very typical, and speeding up this common use via NOEXEC is useful.
40 IOW: rm is "interactive", but not "longterm".
42 Interesting example of an applet which can be NOFORK but if not,
43 then should not be NOEXEC, is "usleep". As NOFORK, it amount to simply
44 nanosleep()ing in the calling program (usually shell). No memory wasted.
45 But if ran as NOEXEC, it would create a potentially long-term process,
46 which would be taking more memory because it did not exec
47 and 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).
54 add-shell - noexec. leaks: open+xfunc
55 addgroup - noexec. leaks
56 adduser - noexec. leaks
60 arp - talks to network: arp -n queries DNS
62 ash - interactive, longterm
66 beep - longterm: beep -r 999999999
67 blkdiscard - noexec. leaks: open+xioctl
69 blockdev - noexec. leaks fd
75 cal - noexec. can be runner: cal -n9999
76 cat - runner: cat HUGEFILE
77 chat - longterm (when used as intended - talking to modem over stdin/out)
78 chattr - noexec. runner
79 chgrp - noexec. runner
80 chmod - noexec. runner
81 chown - noexec. runner
82 chpasswd - longterm? (list of "user:password"s from stdin)
83 chpst - noexec. spawner
84 chroot - noexec. spawner
85 chrt - noexec. spawner
86 chvt - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
87 cksum - noexec. runner
91 conspy - interactive, longterm
92 cp - noexec. sometimes runner
95 crontab - longterm (runs $EDITOR), leaks: open+xasprintf
96 cryptpw - noexec. changes state: with --password-fd=N, moves N to stdin
97 cttyhack - noexec. spawner
99 date - noexec. nofork candidate(needs to stop messing up env, free xasprintf result, not use xfuncs after xasprintf)
100 dc - longterm (eats stdin if no params)
102 deallocvt - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
103 delgroup - noexec. leaks
104 deluser - noexec. leaks
105 depmod - longterm(ish)
106 devmem - hardware (access to device memory may hang)
107 df - noexec. leaks: nested allocs
113 dnsdomainname - noexec. talks to network (may query DNS)
114 dos2unix - noexec. runner
117 dumpkmap - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
118 dumpleases - noexec. leaks: open+xread
120 ed - interactive, longterm
121 egrep - longterm runner ("CMD | egrep ..." may run indefinitely, better to exec to conserve memory)
122 eject - hardware, leaks: open+ioctl_or_perror_and_die, changes state (moves fds)
123 env - noexec. spawner, changes state (env)
124 envdir - noexec. spawner
125 envuidgid - noexec. spawner
127 expr - noexec. leaks: nested allocs
128 factor - longterm (eats stdin if no params)
131 fatattr - noexec. leaks: open+xioctl, complex
132 fbset - hardware, leaks: open+xfunc
133 fbsplash - runner, longterm
134 fdflush - hardware, leaks: open+ioctl_or_perror_and_die
135 fdformat - hardware, longterm
136 fdisk - interactive, longterm
137 fgconsole - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
138 fgrep - longterm runner ("CMD | fgrep ..." may run indefinitely, better to exec to conserve memory)
139 find - noexec. runner
141 flash_eraseall - hardware
142 flash_lock - hardware
143 flash_unlock - hardware
145 flock - spawner, changes state (file locks), let's play safe and not be noexec
146 fold - noexec. runner
148 freeramdisk - noexec. leaks: open+ioctl_or_perror_and_die
149 fsck - interactive, longterm
150 fsck.minix - needs ^C
151 fsfreeze - noexec. leaks: open+xioctl
152 fstrim - noexec. leaks: open+xioctl, find_block_device -> readdir+xstrdup
158 getopt - noexec. leaks: many allocs
159 getty - interactive, longterm
160 grep - longterm runner ("CMD | grep ..." may run indefinitely, better to exec to conserve memory)
167 head - noexec. runner
168 hexdump - noexec. runner
169 hexedit - interactive, longterm
171 hostname - noexec. talks to network (hostname -d may query DNS)
173 hush - interactive, longterm
174 hwclock - hardware (xioctl(RTC_RD_TIME))
180 ifconfig - hardware? (mem_start NN io_addr NN irq NN), leaks: xsocket+ioctl_or_perror_and_die
181 ifenslave - noexec. leaks: xsocket+bb_perror_msg_and_die
188 ionice - noexec. spawner
189 iostat - longterm: "iostat 1" runs indefinitely
192 ipcalc - noexec. ipcalc -h talks to network
200 kbd_mode - noexec. leaks: xopen_nonblocking+xioctl
205 last - runner (I've got 1300 lines of output when tried it)
206 less - interactive, longterm
208 linux32 - noexec. spawner
209 linux64 - noexec. spawner
212 loadfont - noexec. leaks: config_open+bb_error_msg_and_die("map format")
213 loadkmap - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
215 login - suid, interactive, longterm
217 losetup - noexec. complex
222 lsattr - noexec. runner
225 lspci - noexec. too rare to bother for nofork
226 lsscsi - noexec. too rare to bother for nofork
227 lsusb - noexec. too rare to bother for nofork
234 man - spawner, interactive, longterm
235 md5sum - noexec. runner
238 microcom - interactive, longterm
245 mkfs.minix - needs ^C
248 mkpasswd - noexec. changes state: with --password-fd=N, moves N to stdin
250 mktemp - noexec. leaks: xstrdup+concat_path_file
253 more - interactive, longterm
255 mountpoint - noexec. leaks: option -n "print dev name": find_block_device -> readdir+xstrdup
256 mpstat - longterm: "mpstat 1" runs indefinitely
258 mv - noexec. sometimes runner
259 nameif - noexec. openlog(), leaks: config_open2+ioctl_or_perror_and_die
262 netstat - longterm with -c (continuous listing)
263 nice - noexec. spawner
266 nohup - noexec. spawner
271 openvt - longterm: spawns a child and waits for it
272 partprobe - noexec. leaks: open+ioctl_or_perror_and_die(BLKRRPART)
274 paste - noexec. runner
276 pgrep - must fork+exec to get correct /proc/PID/cmdline and comm field
277 pidof - must fork+exec to get correct /proc/PID/cmdline and comm field
278 ping - suid, longterm
279 ping6 - suid, longterm
280 pipe_progress - longterm
282 pkill - must fork+exec to get correct /proc/PID/cmdline and comm field
283 pmap - noexec candidate, leaks: open+xstrdup
286 powertop - interactive, longterm
290 pscan - talks to network
294 raidautorun - noexec. very simple. leaks: open+xioctl
295 rdate - talks to network
296 rdev - noexec. leaks: find_block_device -> readdir+xstrdup
298 readprofile - reads /boot/System.map and /proc/profile, better to free more memory by execing?
302 remove-shell - noexec. leaks: open+xfunc
303 renice - noexec. nofork candidate(uses getpwnam, is that ok?)
304 reset - noexec. spawner (execs "stty")
305 resize - noexec. changes state (signal handlers)
308 rm - noexec. rm -i interactive
311 route - talks to network (may query DNS to convert IPs to names)
314 rtcwake - longterm: puts system to sleep, optimizing this for speed is pointless
315 run-init - spawner, rare, changes state (oh yes), execing may be important to free binary's inode
317 runlevel - noexec. can be nofork if "endutxent()" is called unconditionally, but too rare to bother?
321 script - longterm: pumps script output from slave pty
322 scriptreplay - longterm: plays back "script" saved output, sleeping as necessary.
326 setarch - noexec. spawner
329 setfont - noexec. leaks a lot of stuff
332 setpriv - spawner, changes state, let's play safe and not be noexec
334 setsid - spawner, uses fork_or_rexec() [not audited to work in noexec], let's play safe and not be noexec
335 setuidgid - noexec. spawner
336 sha1sum - noexec. runner
337 sha256sum - noexec. runner
338 sha3sum - noexec. runner
339 sha512sum - noexec. runner
340 showkey - interactive, longterm
342 shuf - noexec. runner
343 slattach - longterm (may sleep forever), uses bb_common_bufsiz1
344 sleep - longterm. Could be nofork, if not the problem of "killall sleep" not killing it.
346 softlimit - noexec. spawner
347 sort - noexec. runner
349 ssl_client - longterm
350 start-stop-daemon - not noexec: uses bb_common_bufsiz1
351 stat - noexec. nofork candidate(needs fewer allocs)
353 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
355 sulogin - noexec. spawner
357 sv - noexec. needs ^C (uses usleep(420000))
358 svc - noexec. needs ^C (uses usleep(420000))
360 swapoff - longterm: may cause memory pressure, execing is beneficial
362 switch_root - spawner, rare, changes state (oh yes), execing may be important to free binary's inode
364 sysctl - noexec. leaks: xstrdup+xmalloc_read
369 taskset - noexec. spawner
372 telnet - interactive, longterm
377 time - spawner, longterm, changes state (signals)
378 timeout - spawner, longterm, changes state (signals)
379 top - interactive, longterm
382 traceroute - suid, longterm
383 traceroute6 - suid, longterm
389 tune2fs - noexec. leaks: open+xfunc
396 ubiupdatevol - hardware
401 umount - noexec. leaks: nested xmalloc
406 unix2dos - noexec. runner
412 uptime - noexec. nofork candidate(is getutxent ok?)
413 users - noexec. nofork candidate(is getutxent ok?)
414 usleep - NOFORK. But what about "killall usleep"?
417 vconfig - noexec. leaks: xsocket+ioctl_or_perror_and_die
418 vi - interactive, longterm
420 volname - hardware (reads CDROM, this can take long-ish if need to spin up)
421 w - noexec. nofork candidate(is getutxent ok?)
428 who - noexec. nofork candidate(is getutxent ok?)
430 whois - talks to network
431 xargs - noexec. spawner