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>
This commit is contained in:
Denys Vlasenko 2016-04-02 18:06:24 +02:00
parent c87e81f944
commit 8220399173
5 changed files with 38 additions and 35 deletions

View 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_EXECVP(prog,cmd) execvp(prog,cmd)
#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__)
#endif #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. */ * in the parent. It must be a macro. */
#define xvfork() \ #define xvfork() \
({ \ ({ \
@ -1006,6 +1007,7 @@ int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
#if BB_MMU #if BB_MMU
pid_t xfork(void) FAST_FUNC; pid_t xfork(void) FAST_FUNC;
#endif #endif
void xvfork_parent_waits_and_exits(void) FAST_FUNC;
/* NOMMU friendy fork+exec: */ /* NOMMU friendy fork+exec: */
pid_t spawn(char **argv) FAST_FUNC; pid_t spawn(char **argv) FAST_FUNC;

View File

@ -83,10 +83,19 @@ int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
} }
#endif #endif
int FAST_FUNC BB_EXECVP_or_die(char **argv) void FAST_FUNC BB_EXECVP_or_die(char **argv)
{ {
BB_EXECVP(argv[0], argv); BB_EXECVP(argv[0], argv);
/* SUSv3-mandated exit codes */ /* SUSv3-mandated exit codes */
xfunc_error_retval = (errno == ENOENT) ? 127 : 126; xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
bb_perror_msg_and_die("can't execute '%s'", argv[0]); 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);
}

View File

@ -659,3 +659,19 @@ pid_t FAST_FUNC xfork(void)
return pid; return pid;
} }
#endif #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 */
}

View File

@ -230,7 +230,7 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
ns->ns_nsfile8 + 3 /* skip over "ns/" */ 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;*/ /*ns_ctx->fd = -1;*/
} }
@ -244,13 +244,13 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
} }
xfchdir(root_fd); xfchdir(root_fd);
xchroot("."); xchroot(".");
/*close(root_fd);*/ close(root_fd);
/*root_fd = -1;*/ /*root_fd = -1;*/
} }
if (wd_fd >= 0) { if (wd_fd >= 0) {
xfchdir(wd_fd); xfchdir(wd_fd);
/*close(wd_fd);*/ close(wd_fd);
/*wd_fd = -1;*/ /*wd_fd = -1;*/
} }
@ -259,14 +259,7 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
* explicitly requested by the user not to. * explicitly requested by the user not to.
*/ */
if (!(opts & OPT_nofork) && (opts & OPT_pid)) { if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
pid_t pid = xvfork(); xvfork_parent_waits_and_exits();
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 */ /* Child continues */
} }
@ -278,9 +271,5 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
if (opts & OPT_setuid) if (opts & OPT_setuid)
xsetuid(uid); xsetuid(uid);
if (*argv) { exec_prog_or_SHELL(argv);
BB_EXECVP_or_die(argv);
}
run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
} }

View File

@ -281,7 +281,7 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
if (fdp.wr >= 0) { if (fdp.wr >= 0) {
close(fdp.wr); /* Release child */ close(fdp.wr); /* Release child */
/*close(fdp.rd);*/ close(fdp.rd); /* should close fd, to not confuse exec'ed PROG */
} }
if (need_mount) { 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. * that'll become PID 1 in this new namespace.
*/ */
if (opts & OPT_fork) { if (opts & OPT_fork) {
pid_t pid = xfork(); xvfork_parent_waits_and_exits();
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 */ /* 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); mount_or_die("proc", proc_mnt_target, "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV);
} }
if (argv[0]) { exec_prog_or_SHELL(argv);
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);
} }