diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am index 5636f70da..33112fb68 100644 --- a/sys-utils/Makemodule.am +++ b/sys-utils/Makemodule.am @@ -287,7 +287,6 @@ if BUILD_UNSHARE usrbin_exec_PROGRAMS += unshare dist_man_MANS += sys-utils/unshare.1 unshare_SOURCES = sys-utils/unshare.c -unshare_LDADD = $(LDADD) libcommon.la endif if BUILD_ARCH diff --git a/sys-utils/unshare.1 b/sys-utils/unshare.1 index c37083d41..1325e3481 100644 --- a/sys-utils/unshare.1 +++ b/sys-utils/unshare.1 @@ -3,15 +3,15 @@ .\" .TH UNSHARE 1 "October 2008" "util-linux" "User Commands" .SH NAME -unshare \- run program with some namespaces unshared or changed from parent +unshare \- run program with some namespaces unshared from parent .SH SYNOPSIS .B unshare .RI [ options ] program .RI [ arguments ] .SH DESCRIPTION -Unshares or migrates specified namespaces from parent process and then executes specified -program. Available namespaces are: +Unshares specified namespaces from parent process and then executes specified +program. Unshareable namespaces are: .TP .BR "mount namespace" mounting and unmounting filesystems will not affect rest of the system @@ -33,43 +33,31 @@ etc. (\fBCLONE_NEWNET\fP flag). .TP See the \fBclone\fR(2) for exact semantics of the flags. .SH OPTIONS -Note when specifying the optional \fB\fP argument, the string of option, -equal sign (=), and the pid must not contain any blanks or other white space. -The correct form is for example --ipc=123 or -i=123. .TP .BR \-h , " \-\-help" Print a help message, .TP -.BR \-m , " \-\-mount " \fI[=pid]\fP -Unshare the mount namespace, or, when a pid is specified, migrate the mount -namespace to the one attached to the specified pid. +.BR \-m , " \-\-mount" +Unshare the mount namespace, .TP -.BR \-u , " \-\-uts " \fI[=pid]\fP -Unshare the UTC namespace, or, when a pid is specified, migrate the uts -namespace to the one attached to the specified pid +.BR \-u , " \-\-uts" +Unshare the UTC namespace, .TP -.BR \-i , " \-\-ipc " \fI[=pid]\fP -Unshare the IPC namespace, or, when a pid is specified, migrate the ipc -namespace to the one attached to the specified pid +.BR \-i , " \-\-ipc" +Unshare the IPC namespace, .TP -.BR \-n , " \-\-net " \fI[=pid]\fP -Unshare the network namespace, or, when a pid is specified, migrate the net -namespace to the one attached to the specified pid +.BR \-n , " \-\-net" +Unshare the network namespace. .SH NOTES The unshare command drops potential privileges before executing the target program. This allows to setuid unshare. -.P -Support for migrating processes between mount and pid namespace is available in -kernels 3.8 and later .SH SEE ALSO .BR unshare (2), -.BR setns (2), .BR clone (2) .SH BUGS None known so far. -.SH AUTHORS +.SH AUTHOR Mikhail Gusarov -Neil Horman .SH AVAILABILITY The unshare command is part of the util-linux package and is available from ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c index 64ea3766f..9de997bdc 100644 --- a/sys-utils/unshare.c +++ b/sys-utils/unshare.c @@ -24,12 +24,10 @@ #include #include #include -#include #include "nls.h" #include "c.h" #include "closestream.h" -#include "strutils.h" #ifndef CLONE_NEWSNS # define CLONE_NEWNS 0x00020000 @@ -62,10 +60,10 @@ static void usage(int status) _(" %s [options] [args...]\n"), program_invocation_short_name); fputs(USAGE_OPTIONS, out); - fputs(_(" -m, --mount [=] unshare or migrate mounts namespace\n" - " -u, --uts [=] unshare or migrate UTS namespace (hostname etc)\n" - " -i, --ipc [=] unshare or migrate System V IPC namespace\n" - " -n, --net [=] unshare or migrate network namespace\n"), out); + fputs(_(" -m, --mount unshare mounts namespace\n" + " -u, --uts unshare UTS namespace (hostname etc)\n" + " -i, --ipc unshare System V IPC namespace\n" + " -n, --net unshare network namespace\n"), out); fputs(USAGE_SEPARATOR, out); fputs(USAGE_HELP, out); @@ -78,18 +76,17 @@ static void usage(int status) int main(int argc, char *argv[]) { static const struct option longopts[] = { - { "help", no_argument, 0, 'h' }, + { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V'}, - { "mount", optional_argument, 0, 'm' }, - { "uts", optional_argument, 0, 'u' }, - { "ipc", optional_argument, 0, 'i' }, - { "net", optional_argument, 0, 'n' }, + { "mount", no_argument, 0, 'm' }, + { "uts", no_argument, 0, 'u' }, + { "ipc", no_argument, 0, 'i' }, + { "net", no_argument, 0, 'n' }, { NULL, 0, 0, 0 } }; - int namespaces[128]; /* /proc/#/ns/ file descriptors */ - size_t i, nscount = 0; /* number of used namespaces[] */ int unshare_flags = 0; + int c; setlocale(LC_MESSAGES, ""); @@ -97,13 +94,7 @@ int main(int argc, char *argv[]) textdomain(PACKAGE); atexit(close_stdout); - memset(namespaces, 0, sizeof(namespaces)); - - while((c = getopt_long(argc, argv, - "hVm::u::i::n::", longopts, NULL)) != -1) { - - const char *ns = NULL; - + while((c = getopt_long(argc, argv, "hVmuin", longopts, NULL)) != -1) { switch(c) { case 'h': usage(EXIT_SUCCESS); @@ -111,58 +102,26 @@ int main(int argc, char *argv[]) printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; case 'm': - ns = "mnt"; - if (!optarg) - unshare_flags |= CLONE_NEWNS; + unshare_flags |= CLONE_NEWNS; break; case 'u': - ns = "uts"; - if (!optarg) - unshare_flags |= CLONE_NEWUTS; + unshare_flags |= CLONE_NEWUTS; break; case 'i': - ns = "ipc"; - if (!optarg) - unshare_flags |= CLONE_NEWIPC; + unshare_flags |= CLONE_NEWIPC; break; case 'n': - ns = "net"; - if (!optarg) - unshare_flags |= CLONE_NEWNET; + unshare_flags |= CLONE_NEWNET; break; default: usage(EXIT_FAILURE); } - - if (ns && optarg) { - pid_t pid; - char path[512]; - - if (nscount >= ARRAY_SIZE(namespaces)) - err(EXIT_FAILURE, _("too many new namespaces specified")); - - if (*optarg == '=') - optarg++; - - pid = strtoul_or_err(optarg, _("failed to parse pid argument")); - - sprintf(path, "/proc/%lu/ns/%s", (unsigned long) pid, ns); - namespaces[nscount] = open(path, O_RDONLY | O_CLOEXEC); - if (namespaces[nscount] < 0) - err(EXIT_FAILURE, _("cannot open %s"), path); - nscount++; - } } - if (optind >= argc) + if(optind >= argc) usage(EXIT_FAILURE); - for (i = 0; i < nscount; i++) { - if (setns(namespaces[i], 0) != 0) - err(EXIT_FAILURE, _("setns failed")); - } - - if (unshare_flags && unshare(unshare_flags) != 0) + if(-1 == unshare(unshare_flags)) err(EXIT_FAILURE, _("unshare failed")); /* drop potential root euid/egid if we had been setuid'd */