nsenter,unshare: share common code; fix a bug of not closing all fds
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 2 Apr 2016 16:06:24 +0000 (18:06 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 2 Apr 2016 16:06:24 +0000 (18:06 +0200)
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>
include/libbb.h
libbb/executable.c
libbb/xfuncs_printf.c
util-linux/nsenter.c
util-linux/unshare.c

index 5b4280e34d2aff963e5d54986a6581cfb7503cb9..64e61cd262af1030c5aeb8b88bdbff931c02f521 100644 (file)
@@ -992,9 +992,10 @@ int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC;
 #define BB_EXECVP(prog,cmd)     execvp(prog,cmd)
 #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__)
 #endif
-int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
+void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
+void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC;
 
-/* xvfork() can't be a _function_, return after vfork mangles stack
+/* xvfork() can't be a _function_, return after vfork in child mangles stack
  * in the parent. It must be a macro. */
 #define xvfork() \
 ({ \
@@ -1006,6 +1007,7 @@ int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
 #if BB_MMU
 pid_t xfork(void) FAST_FUNC;
 #endif
+void xvfork_parent_waits_and_exits(void) FAST_FUNC;
 
 /* NOMMU friendy fork+exec: */
 pid_t spawn(char **argv) FAST_FUNC;
index 85ecc3e6cabcb9d01514672f5d0281192540ce95..05e70312f00b82687447fb784b680f3e5013f65d 100644 (file)
@@ -83,10 +83,19 @@ int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
 }
 #endif
 
-int FAST_FUNC BB_EXECVP_or_die(char **argv)
+void FAST_FUNC BB_EXECVP_or_die(char **argv)
 {
        BB_EXECVP(argv[0], argv);
        /* SUSv3-mandated exit codes */
        xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
        bb_perror_msg_and_die("can't execute '%s'", argv[0]);
 }
+
+/* Typical idiom for applets which exec *optional* PROG [ARGS] */
+void FAST_FUNC exec_prog_or_SHELL(char **argv)
+{
+       if (argv[0]) {
+               BB_EXECVP_or_die(argv);
+       }
+       run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
+}
index 4aa1b5ce2130fe4c56b73f104a162899a7dacfcb..e9222f690654441bd7dfc5f61c66348154593ac9 100644 (file)
@@ -659,3 +659,19 @@ pid_t FAST_FUNC xfork(void)
        return pid;
 }
 #endif
+
+void FAST_FUNC xvfork_parent_waits_and_exits(void)
+{
+       pid_t pid;
+
+       fflush_all();
+       pid = xvfork();
+       if (pid > 0) {
+               /* Parent */
+               int exit_status = wait_for_exitstatus(pid);
+               if (WIFSIGNALED(exit_status))
+                       kill_myself_with_sig(WTERMSIG(exit_status));
+               _exit(WEXITSTATUS(exit_status));
+       }
+       /* Child continues */
+}
index 9c1dabaa868cac86c8f220cfa5c78fe6ffa7dfe3..0dad595cdf9ea336bdef0cdfab0fd66652c05282 100644 (file)
@@ -230,7 +230,7 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
                                ns->ns_nsfile8 + 3 /* skip over "ns/" */
                        );
                }
-               /*close(ns_ctx->fd);*/
+               close(ns_ctx->fd); /* should close fds, to not confuse exec'ed PROG */
                /*ns_ctx->fd = -1;*/
        }
 
@@ -244,13 +244,13 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
                }
                xfchdir(root_fd);
                xchroot(".");
-               /*close(root_fd);*/
+               close(root_fd);
                /*root_fd = -1;*/
        }
 
        if (wd_fd >= 0) {
                xfchdir(wd_fd);
-               /*close(wd_fd);*/
+               close(wd_fd);
                /*wd_fd = -1;*/
        }
 
@@ -259,14 +259,7 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
         * explicitly requested by the user not to.
         */
        if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
-               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);
-               }
+               xvfork_parent_waits_and_exits();
                /* Child continues */
        }
 
@@ -278,9 +271,5 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
        if (opts & OPT_setuid)
                xsetuid(uid);
 
-       if (*argv) {
-               BB_EXECVP_or_die(argv);
-       }
-
-       run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
+       exec_prog_or_SHELL(argv);
 }
index 2a5bea5a60da4839f8902ec61a8d881860ed5747..95a7cb6477505954908defcd891c2cf235832421 100644 (file)
@@ -281,7 +281,7 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
 
        if (fdp.wr >= 0) {
                close(fdp.wr); /* Release child */
-               /*close(fdp.rd);*/
+               close(fdp.rd); /* should close fd, to not confuse exec'ed PROG */
        }
 
        if (need_mount) {
@@ -307,14 +307,7 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
         * that'll become PID 1 in this new namespace.
         */
        if (opts & OPT_fork) {
-               pid_t pid = xfork();
-               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);
-               }
+               xvfork_parent_waits_and_exits();
                /* Child continues */
        }
 
@@ -354,11 +347,5 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
                mount_or_die("proc", proc_mnt_target, "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV);
        }
 
-       if (argv[0]) {
-               BB_EXECVP_or_die(argv);
-       }
-       /* unshare from util-linux 2.27.1, despite not documenting it,
-        * runs a login shell (argv0="-sh") if no PROG is given
-        */
-       run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
+       exec_prog_or_SHELL(argv);
 }