[Bug 7700] New: busybox init calls vfork() but does not immediately call exec(), probably causing downstream pain
bugzilla at busybox.net
bugzilla at busybox.net
Tue Dec 9 04:21:05 UTC 2014
https://bugs.busybox.net/show_bug.cgi?id=7700
Summary: busybox init calls vfork() but does not immediately
call exec(), probably causing downstream pain
Product: Busybox
Version: 1.22.x
Platform: All
OS/Version: Linux
Status: NEW
Severity: major
Priority: P5
Component: Standard Compliance
AssignedTo: unassigned at busybox.net
ReportedBy: eric at aterlo.com
CC: busybox-cvs at busybox.net
Estimated Hours: 0.0
The vfork() man page says that after a vfork(), the child needs to just call
exec(), and nothing else. Don't write to stack variables (with the sole
exception of your pid_t). Don't call any other functions. Don't even return
from the current function. Just call exec(), and if that fails you can call
_exit().
For convenience, here is the relevant hunk of the vfork() man page:
==
DESCRIPTION
Standard Description
(From POSIX.1) The vfork() function has the same effect as fork(2),
except that the behavior is undefined if the process created by vfork()
either modifies any data other than a variable of type pid_t used to
store the return value from vfork(), or returns from the function in
which vfork() was called, or calls any other function before success-
fully calling _exit(2) or one of the exec(3) family of functions.
Linux Description
vfork(), just like fork(2), creates a child process of the calling
process. For details and return value and errors, see fork(2).
vfork() is a special case of clone(2). It is used to create new pro-
cesses without copying the page tables of the parent process. It may
be useful in performance-sensitive applications where a child is cre-
ated which then immediately issues an execve(2).
vfork() differs from fork(2) in that the parent is suspended until the
child terminates (either normally, by calling _exit(2), or abnormally,
after delivery of a fatal signal), or it makes a call to execve(2).
Until that point, the child shares all memory with its parent, includ-
ing the stack. The child must not return from the current function or
call exit(3), but may call _exit(2).
Signal handlers are inherited, but not shared. Signals to the parent
arrive after the child releases the parent's memory (i.e., after the
child terminates or calls execve(2)).
==
In busybox's init.c, run() violates most of those requirements.
I am currently investigating a bug on ASUS routers (which make heavy use of
busybox) in which certain processes unexpectedly are blocking a wide variety of
signals, presumably because they are inheriting bad masks from their parents
across fork()/exec() calls. This may have something to do with the races in
busybox's init.c:run(), though I have not yet proven this.
For example, after running 'tail -F', I can't type control-C to kill it,
because it has inherited a blocking mask that includes SIGINT:
==
admin@(none):/proc/2741# ps w | grep tail
6778 admin 1552 S tail -F /tmp/syslog.log
admin@(none):/proc/2741# cat /proc/6778/status | grep Sig
SigQ: 10/2047
SigPnd: 00000000000000000000000000000000
SigBlk: 0000000000000000000000008001e007
SigIgn: 00000000000000000000000040000006
SigCgt: 00000000000000000000000000000000
admin@(none):/proc/2741# kill 6778
admin@(none):/proc/2741# ps w | grep tail
6778 admin 1552 S tail -F /tmp/syslog.log
admin@(none):/proc/2741#
==
The SigBlk value of 8001e007 corresponds to SIGHUP, SIGINT, SIGQUIT, SIGALRM,
SIGTERM, SIGUSR1, and SIGUSR2.
As you can imagine, this kind of thing makes life pretty miserable on the OS in
general -- all those rc.d scripts that rely on TERM to shut things down, all
those programs that rely on the delivery of SIGALRM for timer events, or on
SIGHUP to re-read their configs, etc etc.
Again, I am not 100% certain that the unclean handling of vfork() is to blame.
I will follow up if I am able to prove that it is.
--
Configure bugmail: https://bugs.busybox.net/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.
More information about the busybox-cvs
mailing list