aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-04-02 18:06:24 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-04-02 18:06:24 +0200
commit8220399173cf8d25e37059cadac96ac30f94e82a (patch)
treeffe5ae4a783c8ddeceda15f57eae74ee69feebea
parentc87e81f9440278dd46a3eddd1e0f4773afd46a95 (diff)
downloadbusybox-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.h6
-rw-r--r--libbb/executable.c11
-rw-r--r--libbb/xfuncs_printf.c16
-rw-r--r--util-linux/nsenter.c21
-rw-r--r--util-linux/unshare.c19
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
995int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; 995void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
996void 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
1007pid_t xfork(void) FAST_FUNC; 1008pid_t xfork(void) FAST_FUNC;
1008#endif 1009#endif
1010void xvfork_parent_waits_and_exits(void) FAST_FUNC;
1009 1011
1010/* NOMMU friendy fork+exec: */ 1012/* NOMMU friendy fork+exec: */
1011pid_t spawn(char **argv) FAST_FUNC; 1013pid_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
86int FAST_FUNC BB_EXECVP_or_die(char **argv) 86void 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] */
95void 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
663void 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}