diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-04-02 18:06:24 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-04-02 18:06:24 +0200 |
commit | 8220399173cf8d25e37059cadac96ac30f94e82a (patch) | |
tree | ffe5ae4a783c8ddeceda15f57eae74ee69feebea | |
parent | c87e81f9440278dd46a3eddd1e0f4773afd46a95 (diff) | |
download | busybox-w32-8220399173cf8d25e37059cadac96ac30f94e82a.tar.gz busybox-w32-8220399173cf8d25e37059cadac96ac30f94e82a.tar.bz2 busybox-w32-8220399173cf8d25e37059cadac96ac30f94e82a.zip |
nsenter,unshare: share common code; fix a bug of not closing all fds
function old new delta
xvfork_parent_waits_and_exits - 64 +64
exec_prog_or_SHELL - 39 +39
unshare_main 873 810 -63
nsenter_main 663 596 -67
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/2 up/down: 106/-130) Total: -27 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/libbb.h | 6 | ||||
-rw-r--r-- | libbb/executable.c | 11 | ||||
-rw-r--r-- | libbb/xfuncs_printf.c | 16 | ||||
-rw-r--r-- | util-linux/nsenter.c | 21 | ||||
-rw-r--r-- | util-linux/unshare.c | 19 |
5 files changed, 38 insertions, 35 deletions
diff --git a/include/libbb.h b/include/libbb.h index 5b4280e34..64e61cd26 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -992,9 +992,10 @@ int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC; | |||
992 | #define BB_EXECVP(prog,cmd) execvp(prog,cmd) | 992 | #define BB_EXECVP(prog,cmd) execvp(prog,cmd) |
993 | #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) | 993 | #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) |
994 | #endif | 994 | #endif |
995 | int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; | 995 | void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; |
996 | void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC; | ||
996 | 997 | ||
997 | /* xvfork() can't be a _function_, return after vfork mangles stack | 998 | /* xvfork() can't be a _function_, return after vfork in child mangles stack |
998 | * in the parent. It must be a macro. */ | 999 | * in the parent. It must be a macro. */ |
999 | #define xvfork() \ | 1000 | #define xvfork() \ |
1000 | ({ \ | 1001 | ({ \ |
@@ -1006,6 +1007,7 @@ int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; | |||
1006 | #if BB_MMU | 1007 | #if BB_MMU |
1007 | pid_t xfork(void) FAST_FUNC; | 1008 | pid_t xfork(void) FAST_FUNC; |
1008 | #endif | 1009 | #endif |
1010 | void xvfork_parent_waits_and_exits(void) FAST_FUNC; | ||
1009 | 1011 | ||
1010 | /* NOMMU friendy fork+exec: */ | 1012 | /* NOMMU friendy fork+exec: */ |
1011 | pid_t spawn(char **argv) FAST_FUNC; | 1013 | pid_t spawn(char **argv) FAST_FUNC; |
diff --git a/libbb/executable.c b/libbb/executable.c index 85ecc3e6c..05e70312f 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -83,10 +83,19 @@ int FAST_FUNC BB_EXECVP(const char *file, char *const argv[]) | |||
83 | } | 83 | } |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | int FAST_FUNC BB_EXECVP_or_die(char **argv) | 86 | void FAST_FUNC BB_EXECVP_or_die(char **argv) |
87 | { | 87 | { |
88 | BB_EXECVP(argv[0], argv); | 88 | BB_EXECVP(argv[0], argv); |
89 | /* SUSv3-mandated exit codes */ | 89 | /* SUSv3-mandated exit codes */ |
90 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; | 90 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; |
91 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | 91 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); |
92 | } | 92 | } |
93 | |||
94 | /* Typical idiom for applets which exec *optional* PROG [ARGS] */ | ||
95 | void FAST_FUNC exec_prog_or_SHELL(char **argv) | ||
96 | { | ||
97 | if (argv[0]) { | ||
98 | BB_EXECVP_or_die(argv); | ||
99 | } | ||
100 | run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL); | ||
101 | } | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 4aa1b5ce2..e9222f690 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -659,3 +659,19 @@ pid_t FAST_FUNC xfork(void) | |||
659 | return pid; | 659 | return pid; |
660 | } | 660 | } |
661 | #endif | 661 | #endif |
662 | |||
663 | void FAST_FUNC xvfork_parent_waits_and_exits(void) | ||
664 | { | ||
665 | pid_t pid; | ||
666 | |||
667 | fflush_all(); | ||
668 | pid = xvfork(); | ||
669 | if (pid > 0) { | ||
670 | /* Parent */ | ||
671 | int exit_status = wait_for_exitstatus(pid); | ||
672 | if (WIFSIGNALED(exit_status)) | ||
673 | kill_myself_with_sig(WTERMSIG(exit_status)); | ||
674 | _exit(WEXITSTATUS(exit_status)); | ||
675 | } | ||
676 | /* Child continues */ | ||
677 | } | ||
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index 9c1dabaa8..0dad595cd 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c | |||
@@ -230,7 +230,7 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv) | |||
230 | ns->ns_nsfile8 + 3 /* skip over "ns/" */ | 230 | ns->ns_nsfile8 + 3 /* skip over "ns/" */ |
231 | ); | 231 | ); |
232 | } | 232 | } |
233 | /*close(ns_ctx->fd);*/ | 233 | close(ns_ctx->fd); /* should close fds, to not confuse exec'ed PROG */ |
234 | /*ns_ctx->fd = -1;*/ | 234 | /*ns_ctx->fd = -1;*/ |
235 | } | 235 | } |
236 | 236 | ||
@@ -244,13 +244,13 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv) | |||
244 | } | 244 | } |
245 | xfchdir(root_fd); | 245 | xfchdir(root_fd); |
246 | xchroot("."); | 246 | xchroot("."); |
247 | /*close(root_fd);*/ | 247 | close(root_fd); |
248 | /*root_fd = -1;*/ | 248 | /*root_fd = -1;*/ |
249 | } | 249 | } |
250 | 250 | ||
251 | if (wd_fd >= 0) { | 251 | if (wd_fd >= 0) { |
252 | xfchdir(wd_fd); | 252 | xfchdir(wd_fd); |
253 | /*close(wd_fd);*/ | 253 | close(wd_fd); |
254 | /*wd_fd = -1;*/ | 254 | /*wd_fd = -1;*/ |
255 | } | 255 | } |
256 | 256 | ||
@@ -259,14 +259,7 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv) | |||
259 | * explicitly requested by the user not to. | 259 | * explicitly requested by the user not to. |
260 | */ | 260 | */ |
261 | if (!(opts & OPT_nofork) && (opts & OPT_pid)) { | 261 | if (!(opts & OPT_nofork) && (opts & OPT_pid)) { |
262 | pid_t pid = xvfork(); | 262 | xvfork_parent_waits_and_exits(); |
263 | if (pid > 0) { | ||
264 | /* Parent */ | ||
265 | int exit_status = wait_for_exitstatus(pid); | ||
266 | if (WIFSIGNALED(exit_status)) | ||
267 | kill_myself_with_sig(WTERMSIG(exit_status)); | ||
268 | return WEXITSTATUS(exit_status); | ||
269 | } | ||
270 | /* Child continues */ | 263 | /* Child continues */ |
271 | } | 264 | } |
272 | 265 | ||
@@ -278,9 +271,5 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv) | |||
278 | if (opts & OPT_setuid) | 271 | if (opts & OPT_setuid) |
279 | xsetuid(uid); | 272 | xsetuid(uid); |
280 | 273 | ||
281 | if (*argv) { | 274 | exec_prog_or_SHELL(argv); |
282 | BB_EXECVP_or_die(argv); | ||
283 | } | ||
284 | |||
285 | run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL); | ||
286 | } | 275 | } |
diff --git a/util-linux/unshare.c b/util-linux/unshare.c index 2a5bea5a6..95a7cb647 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c | |||
@@ -281,7 +281,7 @@ int unshare_main(int argc UNUSED_PARAM, char **argv) | |||
281 | 281 | ||
282 | if (fdp.wr >= 0) { | 282 | if (fdp.wr >= 0) { |
283 | close(fdp.wr); /* Release child */ | 283 | close(fdp.wr); /* Release child */ |
284 | /*close(fdp.rd);*/ | 284 | close(fdp.rd); /* should close fd, to not confuse exec'ed PROG */ |
285 | } | 285 | } |
286 | 286 | ||
287 | if (need_mount) { | 287 | if (need_mount) { |
@@ -307,14 +307,7 @@ int unshare_main(int argc UNUSED_PARAM, char **argv) | |||
307 | * that'll become PID 1 in this new namespace. | 307 | * that'll become PID 1 in this new namespace. |
308 | */ | 308 | */ |
309 | if (opts & OPT_fork) { | 309 | if (opts & OPT_fork) { |
310 | pid_t pid = xfork(); | 310 | xvfork_parent_waits_and_exits(); |
311 | if (pid > 0) { | ||
312 | /* Parent */ | ||
313 | int exit_status = wait_for_exitstatus(pid); | ||
314 | if (WIFSIGNALED(exit_status)) | ||
315 | kill_myself_with_sig(WTERMSIG(exit_status)); | ||
316 | return WEXITSTATUS(exit_status); | ||
317 | } | ||
318 | /* Child continues */ | 311 | /* Child continues */ |
319 | } | 312 | } |
320 | 313 | ||
@@ -354,11 +347,5 @@ int unshare_main(int argc UNUSED_PARAM, char **argv) | |||
354 | mount_or_die("proc", proc_mnt_target, "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV); | 347 | mount_or_die("proc", proc_mnt_target, "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV); |
355 | } | 348 | } |
356 | 349 | ||
357 | if (argv[0]) { | 350 | exec_prog_or_SHELL(argv); |
358 | BB_EXECVP_or_die(argv); | ||
359 | } | ||
360 | /* unshare from util-linux 2.27.1, despite not documenting it, | ||
361 | * runs a login shell (argv0="-sh") if no PROG is given | ||
362 | */ | ||
363 | run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL); | ||
364 | } | 351 | } |