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 - 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
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
147 free - noexec. nofork candidate(struct globals, needs to close /proc/meminfo fd)
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
170 hostname - noexec. talks to network (hostname -d may query DNS)
172 hush - interactive, longterm
173 hwclock - hardware (xioctl(RTC_RD_TIME))
179 ifconfig - hardware? (mem_start NN io_addr NN irq NN), leaks: xsocket+ioctl_or_perror_and_die
180 ifenslave - noexec. leaks: xsocket+bb_perror_msg_and_die
187 ionice - noexec. spawner
188 iostat - longterm: "iostat 1" runs indefinitely
189 ip - noexec candidate
190 ipaddr - noexec candidate
191 ipcalc - noexec. ipcalc -h talks to network
194 iplink - noexec candidate
195 ipneigh - noexec candidate
196 iproute - noexec candidate
197 iprule - noexec candidate
198 iptunnel - noexec candidate
199 kbd_mode - noexec. leaks: xopen_nonblocking+xioctl
204 last - runner (I've got 1300 lines of output when tried it)
205 less - interactive, longterm
207 linux32 - noexec. spawner
208 linux64 - noexec. spawner
211 loadfont - noexec. leaks: config_open+bb_error_msg_and_die("map format")
212 loadkmap - noexec. leaks: get_console_fd_or_die() may open a new fd, or return one of stdio fds
214 login - suid, interactive, longterm
216 losetup - noexec. complex
221 lsattr - noexec. runner
224 lspci - noexec. too rare to bother for nofork
225 lsscsi - noexec. too rare to bother for nofork
226 lsusb - noexec. too rare to bother for nofork
233 man - spawner, interactive, longterm
234 md5sum - noexec. runner
237 microcom - interactive, longterm
243 mkfs.minix - needs ^C
246 mkpasswd - noexec. changes state: with --password-fd=N, moves N to stdin
248 mktemp - noexec. leaks: xstrdup+concat_path_file
251 more - interactive, longterm
253 mountpoint - noexec. leaks: option -n "print dev name": find_block_device -> readdir+xstrdup
254 mpstat - longterm: "mpstat 1" runs indefinitely
256 mv - noexec candidate, runner
257 nameif - noexec. openlog(), leaks: config_open2+ioctl_or_perror_and_die
260 netstat - longterm with -c (continuous listing)
261 nice - noexec. spawner
264 nohup - noexec. spawner
268 openvt - longterm: spawns a child and waits for it
269 partprobe - noexec. leaks: open+ioctl_or_perror_and_die(BLKRRPART)
271 paste - noexec. runner
273 pgrep - must fork+exec to get correct /proc/PID/cmdline and comm field
274 pidof - must fork+exec to get correct /proc/PID/cmdline and comm field
275 ping - suid, longterm
276 ping6 - suid, longterm
277 pipe_progress - longterm
279 pkill - must fork+exec to get correct /proc/PID/cmdline and comm field
280 pmap - noexec candidate, leaks: open+xstrdup
283 powertop - interactive, longterm
287 pscan - talks to network
291 raidautorun - noexec. very simple. leaks: open+xioctl
292 rdate - talks to network
293 rdev - noexec. leaks: find_block_device -> readdir+xstrdup
295 readprofile - reads /boot/System.map and /proc/profile, better to free more memory by execing?
299 remove-shell - noexec. leaks: open+xfunc
300 renice - noexec. nofork candidate(uses getpwnam, is that ok?)
301 reset - noexec. spawner (execs "stty")
302 resize - noexec. changes state (signal handlers)
304 rm - noexec. rm -i interactive
307 route - talks to network (may query DNS to convert IPs to names)
310 rtcwake - longterm: puts system to sleep, optimizing this for speed is pointless
312 runlevel - noexec. can be nofork if "endutxent()" is called unconditionally, but too rare to bother?
316 script - longterm: pumps script output from slave pty
317 scriptreplay - longterm: plays back "script" saved output, sleeping as necessary.
321 setarch - noexec. spawner
323 setfont - noexec. leaks a lot of stuff
326 setpriv - spawner, changes state, let's play safe and not be noexec
328 setsid - spawner, uses fork_or_rexec() [not audited to work in noexec], let's play safe and not be noexec
329 setuidgid - noexec. spawner
330 sha1sum - noexec. runner
331 sha256sum - noexec. runner
332 sha3sum - noexec. runner
333 sha512sum - noexec. runner
334 showkey - interactive, longterm
336 shuf - noexec. runner
337 slattach - longterm (may sleep forever), uses bb_common_bufsiz1
338 sleep - longterm. Could be nofork, if not the problem of "killall sleep" not killing it.
340 softlimit - noexec. spawner
341 sort - noexec. runner
343 ssl_client - longterm
344 start-stop-daemon - not noexec: uses bb_common_bufsiz1
345 stat - noexec. nofork candidate(needs fewer allocs)
347 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
349 sulogin - noexec. spawner
351 sv - noexec. needs ^C (uses usleep(420000))
352 svc - noexec. needs ^C (uses usleep(420000))
354 swapoff - longterm: may cause memory pressure, execing is beneficial
356 switch_root - spawner, rare, changes state (oh yes), execing may be important to free binary's inode
358 sysctl - noexec. leaks: xstrdup+xmalloc_read
363 taskset - noexec. spawner
366 telnet - interactive, longterm
371 time - spawner, longterm, changes state (signals)
372 timeout - spawner, longterm, changes state (signals)
373 top - interactive, longterm
376 traceroute - suid, longterm
377 traceroute6 - suid, longterm
383 tune2fs - noexec. leaks: open+xfunc
390 ubiupdatevol - hardware
395 umount - noexec. leaks: nested xmalloc
400 unix2dos - noexec. runner
406 uptime - noexec. nofork candidate(is getutxent ok?)
407 users - noexec. nofork candidate(is getutxent ok?)
408 usleep - NOFORK. But what about "killall usleep"?
411 vconfig - noexec. leaks: xsocket+ioctl_or_perror_and_die
412 vi - interactive, longterm
414 volname - hardware (reads CDROM, this can take long-ish if need to spin up)
415 w - noexec. nofork candidate(is getutxent ok?)
422 who - noexec. nofork candidate(is getutxent ok?)
424 whois - talks to network
425 xargs - noexec. spawner