*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
//config:config NSENTER
-//config: bool "nsenter"
+//config: bool "nsenter (8.6 kb)"
//config: default y
//config: select PLATFORM_LINUX
//config: help
-//config: Run program with namespaces of other processes.
-//config:
-//config:config FEATURE_NSENTER_LONG_OPTS
-//config: bool "Enable long options"
-//config: default y
-//config: depends on NSENTER && LONG_OPTS
-//config: help
-//config: Support long options for the nsenter applet. This makes
-//config: the busybox implementation more compatible with upstream.
+//config: Run program with namespaces of other processes.
//applet:IF_NSENTER(APPLET(nsenter, BB_DIR_USR_BIN, BB_SUID_DROP))
//usage:#define nsenter_trivial_usage
//usage: "[OPTIONS] [PROG [ARGS]]"
-//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS
-//usage:#define nsenter_full_usage "\n"
-//usage: "\n -t, --target=PID Target process to get namespaces from"
-//usage: "\n -m, --mount[=FILE] Enter mount namespace"
-//usage: "\n -u, --uts[=FILE] Enter UTS namespace (hostname etc)"
-//usage: "\n -i, --ipc[=FILE] Enter System V IPC namespace"
-//usage: "\n -n, --net[=FILE] Enter network namespace"
-//usage: "\n -p, --pid[=FILE] Enter pid namespace"
-//usage: "\n -U, --user[=FILE] Enter user namespace"
-//usage: "\n -S, --setuid=UID Set uid in entered namespace"
-//usage: "\n -G, --setgid=GID Set gid in entered namespace"
-//usage: "\n --preserve-credentials Don't touch uids or gids"
-//usage: "\n -r, --root[=DIR] Set root directory"
-//usage: "\n -w, --wd[=DIR] Set working directory"
-//usage: "\n -F, --no-fork Don't fork before exec'ing PROG"
-//usage:#else
//usage:#define nsenter_full_usage "\n"
//usage: "\n -t PID Target process to get namespaces from"
//usage: "\n -m[FILE] Enter mount namespace"
//usage: "\n -U[FILE] Enter user namespace"
//usage: "\n -S UID Set uid in entered namespace"
//usage: "\n -G GID Set gid in entered namespace"
+//usage: IF_LONG_OPTS(
+//usage: "\n --preserve-credentials Don't touch uids or gids"
+//usage: )
//usage: "\n -r[DIR] Set root directory"
//usage: "\n -w[DIR] Set working directory"
//usage: "\n -F Don't fork before exec'ing PROG"
-//usage:#endif
#include <sched.h>
+#ifndef CLONE_NEWUTS
+# define CLONE_NEWUTS 0x04000000
+#endif
+#ifndef CLONE_NEWIPC
+# define CLONE_NEWIPC 0x08000000
+#endif
+#ifndef CLONE_NEWUSER
+# define CLONE_NEWUSER 0x10000000
+#endif
+#ifndef CLONE_NEWPID
+# define CLONE_NEWPID 0x20000000
+#endif
+#ifndef CLONE_NEWNET
+# define CLONE_NEWNET 0x40000000
+#endif
+
#include "libbb.h"
struct namespace_descr {
OPT_root = 1 << 9,
OPT_wd = 1 << 10,
OPT_nofork = 1 << 11,
- OPT_prescred = (1 << 12) * ENABLE_FEATURE_NSENTER_LONG_OPTS,
+ OPT_prescred = (1 << 12) * ENABLE_LONG_OPTS,
};
enum {
NS_USR_POS = 0,
/*
* Upstream nsenter doesn't support the short option for --preserve-credentials
*/
-static const char opt_str[] = "U::i::u::n::p::m::""t+S+G+r::w::F";
+static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t:+S:+G:+r::w::F";
-#if ENABLE_FEATURE_NSENTER_LONG_OPTS
+#if ENABLE_LONG_OPTS
static const char nsenter_longopts[] ALIGN1 =
"user\0" Optional_argument "U"
"ipc\0" Optional_argument "i"
"uts\0" Optional_argument "u"
- "network\0" Optional_argument "n"
+ "net\0" Optional_argument "n"
"pid\0" Optional_argument "p"
"mount\0" Optional_argument "m"
"target\0" Required_argument "t"
memset(ns_ctx_list, 0, sizeof(ns_ctx_list));
- IF_FEATURE_NSENTER_LONG_OPTS(applet_long_options = nsenter_longopts);
- opts = getopt32(argv, opt_str,
+ opts = getopt32long(argv, opt_str, nsenter_longopts,
&ns_ctx_list[NS_USR_POS].path,
&ns_ctx_list[NS_IPC_POS].path,
&ns_ctx_list[NS_UTS_POS].path,
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;*/
}
}
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;*/
}
* 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 */
}
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);
}