*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
-
//config:config UNSHARE
//config: bool "unshare"
//config: default y
-//config: depends on LONG_OPTS && !NOMMU
+//config: depends on !NOMMU
//config: select PLATFORM_LINUX
+//config: select LONG_OPTS
//config: help
//config: Run program with some namespaces unshared from parent.
-// depends on LONG_OPTS: it is awkward to exclude code which handles --propagation
+// needs LONG_OPTS: it is awkward to exclude code which handles --propagation
// and --setgroups based on LONG_OPTS, so instead applet requires LONG_OPTS.
// depends on !NOMMU: we need fork()
//usage:#define unshare_trivial_usage
//usage: "[OPTIONS] [PROG [ARGS]]"
//usage:#define unshare_full_usage "\n"
-//usage: "\n -m, --mount[=FILE] Unshare mount namespace"
-//usage: "\n -u, --uts[=FILE] Unshare UTS namespace (hostname etc.)"
-//usage: "\n -i, --ipc[=FILE] Unshare System V IPC namespace"
-//usage: "\n -n, --net[=FILE] Unshare network namespace"
-//usage: "\n -p, --pid[=FILE] Unshare PID namespace"
-//usage: "\n -U, --user[=FILE} Unshare user namespace"
-//usage: "\n -f, --fork Fork before execing PROG"
-//usage: "\n -r, --map-root-user Map current user to root (implies -u)"
+//usage: "\n -m,--mount[=FILE] Unshare mount namespace"
+//usage: "\n -u,--uts[=FILE] Unshare UTS namespace (hostname etc.)"
+//usage: "\n -i,--ipc[=FILE] Unshare System V IPC namespace"
+//usage: "\n -n,--net[=FILE] Unshare network namespace"
+//usage: "\n -p,--pid[=FILE] Unshare PID namespace"
+//usage: "\n -U,--user[=FILE] Unshare user namespace"
+//usage: "\n -f,--fork Fork before execing PROG"
+//usage: "\n -r,--map-root-user Map current user to root (implies -U)"
//usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)"
//usage: "\n --propagation slave|shared|private|unchanged"
//usage: "\n Modify mount propagation in mount namespace"
//usage: "\n --setgroups allow|deny Control the setgroups syscall in user namespaces"
#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 <sys/mount.h>
+#ifndef MS_REC
+# define MS_REC (1 << 14)
+#endif
+#ifndef MS_PRIVATE
+# define MS_PRIVATE (1 << 18)
+#endif
+#ifndef MS_SLAVE
+# define MS_SLAVE (1 << 19)
+#endif
+#ifndef MS_SHARED
+# define MS_SHARED (1 << 20)
+#endif
+
#include "libbb.h"
static void mount_or_die(const char *source, const char *target,
}
}
-// TODO: move to libbb
-static int wait_for_exitstatus(pid_t pid)
-{
- int exit_status, n;
-
- n = safe_waitpid(pid, &exit_status, 0);
- if (n < 0)
- bb_perror_msg_and_die("waitpid");
- return exit_status;
-}
-
-/*
- * Longest possible path to a procfs file used in unshare. Must be able to
- * contain the '/proc/' string, the '/ns/user' string which is the longest
- * namespace name and a 32-bit integer representing the process ID.
- */
#define PATH_PROC_SETGROUPS "/proc/self/setgroups"
#define PATH_PROC_UIDMAP "/proc/self/uid_map"
#define PATH_PROC_GIDMAP "/proc/self/gid_map"
OPT_mount = 1 << 0,
OPT_uts = 1 << 1,
OPT_ipc = 1 << 2,
- OPT_network = 1 << 3,
+ OPT_net = 1 << 3,
OPT_pid = 1 << 4,
OPT_user = 1 << 5, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */
OPT_fork = 1 << 6,
* we are forced to use "fake" letters for them.
* '+': stop at first non-option.
*/
-static const char opt_str[] = "+muinpU""fr""\xfd::""\xfe:""\xff:";
+static const char opt_str[] ALIGN1 = "+muinpU""fr""\xfd::""\xfe:""\xff:";
static const char unshare_longopts[] ALIGN1 =
"mount\0" Optional_argument "\xf0"
"uts\0" Optional_argument "\xf1"
"ipc\0" Optional_argument "\xf2"
- "network\0" Optional_argument "\xf3"
+ "net\0" Optional_argument "\xf3"
"pid\0" Optional_argument "\xf4"
"user\0" Optional_argument "\xf5"
"fork\0" No_argument "f"
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) {
* 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 */
}
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);
}