nsenter,unshare: don't use xvfork_parent_waits_and_exits(), it SEGVs on ppc64le
No binary (build failed)
gcc -Wp,-MD,applets/.usage.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Iinclude -Iinclude -o applets/usage applets/usage.c
(log yok)
| @@ -696,6 +696,14 @@ pid_t FAST_FUNC xfork(void) | |
| } | |
| #endif | |
| + | #if 0 |
| + | /* DO NOT DO THIS. This can't be a function. |
| + | * It works on some arches (x86) but fails on others (ppc64le: SEGV). |
| + | * The reason is: the child returns from this function |
| + | * and likely pops up the stack in an arch-dependent way. |
| + | * When child eventually exits or execs, parent "reappear" |
| + | * in the now-unwound stack (!) and the behavior is undefined. |
| + | */ |
| void FAST_FUNC xvfork_parent_waits_and_exits(void) | |
| { | |
| pid_t pid; | |
| @@ -711,6 +719,7 @@ void FAST_FUNC xvfork_parent_waits_and_exits(void) | |
| } | |
| /* Child continues */ | |
| } | |
| + | #endif |
| // Useful when we do know that pid is valid, and we just want to wait | |
| // for it to exit. Not existing pid is fatal. waitpid() status is not returned. | |
| @@ -251,7 +251,14 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv) | |
| * explicitly requested by the user not to. | |
| */ | |
| if (!(opts & OPT_nofork) && (opts & OPT_pid)) { | |
| - | xvfork_parent_waits_and_exits(); |
| + | pid_t pid = xvfork(); |
| + | if (pid > 0) { |
| + | /* Parent */ |
| + | int exit_status = wait_for_exitstatus(pid); |
| + | if (WIFSIGNALED(exit_status)) |
| + | kill_myself_with_sig(WTERMSIG(exit_status)); |
| + | return WEXITSTATUS(exit_status); |
| + | } |
| /* Child continues */ | |
| } | |
| @@ -333,7 +333,14 @@ int unshare_main(int argc UNUSED_PARAM, char **argv) | |
| * that'll become PID 1 in this new namespace. | |
| */ | |
| if (opts & OPT_fork) { | |
| - | xvfork_parent_waits_and_exits(); |
| + | pid_t pid = xvfork(); |
| + | if (pid > 0) { |
| + | /* Parent */ |
| + | int exit_status = wait_for_exitstatus(pid); |
| + | if (WIFSIGNALED(exit_status)) |
| + | kill_myself_with_sig(WTERMSIG(exit_status)); |
| + | return WEXITSTATUS(exit_status); |
| + | } |
| /* Child continues */ | |
| } | |