531551
diff -up util-linux-2.23.2/include/pathnames.h.kzak util-linux-2.23.2/include/pathnames.h
531551
--- util-linux-2.23.2/include/pathnames.h.kzak	2015-06-26 10:00:19.111877564 +0200
531551
+++ util-linux-2.23.2/include/pathnames.h	2015-06-26 10:00:51.623630869 +0200
531551
@@ -85,6 +85,10 @@
531551
 #define _PATH_PROC_LOCKS        "/proc/locks"
531551
 #define _PATH_PROC_CDROMINFO	"/proc/sys/dev/cdrom/info"
531551
 
531551
+#define _PATH_PROC_UIDMAP	"/proc/self/uid_map"
531551
+#define _PATH_PROC_GIDMAP	"/proc/self/gid_map"
531551
+#define _PATH_PROC_SETGROUPS	"/proc/self/setgroups"
531551
+
531551
 #define _PATH_PROC_ATTR_CURRENT	"/proc/self/attr/current"
531551
 #define _PATH_PROC_ATTR_EXEC	"/proc/self/attr/exec"
531551
 #define _PATH_PROC_CAPLASTCAP	"/proc/sys/kernel/cap_last_cap"
531551
diff -up util-linux-2.23.2/sys-utils/Makemodule.am.kzak util-linux-2.23.2/sys-utils/Makemodule.am
531551
diff -up util-linux-2.23.2/sys-utils/nsenter.1.kzak util-linux-2.23.2/sys-utils/nsenter.1
531551
--- util-linux-2.23.2/sys-utils/nsenter.1.kzak	2015-06-26 09:58:39.468633643 +0200
531551
+++ util-linux-2.23.2/sys-utils/nsenter.1	2015-06-26 09:58:51.672541041 +0200
531551
@@ -1,44 +1,45 @@
531551
-.TH NSENTER 1 "January 2013" "util-linux" "User Commands"
531551
+.TH NSENTER 1 "June 2013" "util-linux" "User Commands"
531551
 .SH NAME
531551
 nsenter \- run program with namespaces of other processes
531551
 .SH SYNOPSIS
531551
 .B nsenter
531551
-.RI [ options ]
531551
-.RI [ program ]
531551
-.RI [ arguments ]
531551
+[options]
531551
+.RI [ program
531551
+.RI [ arguments ]]
531551
 .SH DESCRIPTION
531551
 Enters the namespaces of one or more other processes and then executes the specified
531551
 program.  Enterable namespaces are:
531551
 .TP
531551
 .B mount namespace
531551
-mounting and unmounting filesystems will not affect rest of the system
531551
+Mounting and unmounting filesystems will not affect the rest of the system
531551
 .RB ( CLONE_\:NEWNS
531551
-flag), except for filesystems which are explicitly marked as shared (by mount
531551
---make-\:shared).  See /proc\:/self\:/mountinfo for the shared flag.
531551
+flag), except for filesystems which are explicitly marked as shared (with
531551
+\fBmount --make-\:shared\fP; see \fI/proc\:/self\:/mountinfo\fP for the
531551
+\fBshared\fP flag).
531551
 .TP
531551
 .B UTS namespace
531551
-setting hostname, domainname will not affect rest of the system
531551
+Setting hostname or domainname will not affect the rest of the system.
531551
 .RB ( CLONE_\:NEWUTS
531551
-flag).
531551
+flag)
531551
 .TP
531551
 .B IPC namespace
531551
-process will have independent namespace for System V message queues, semaphore
531551
-sets and shared memory segments
531551
+The process will have an independent namespace for System V message queues,
531551
+semaphore sets and shared memory segments.
531551
 .RB ( CLONE_\:NEWIPC
531551
-flag).
531551
+flag)
531551
 .TP
531551
 .B network namespace
531551
-process will have independent IPv4 and IPv6 stacks, IP routing tables, firewall
531551
-rules, the
531551
+The process will have independent IPv4 and IPv6 stacks, IP routing tables,
531551
+firewall rules, the
531551
 .I /proc\:/net
531551
 and
531551
 .I /sys\:/class\:/net
531551
-directory trees, sockets etc.
531551
+directory trees, sockets, etc.
531551
 .RB ( CLONE_\:NEWNET
531551
-flag).
531551
+flag)
531551
 .TP
531551
 .B PID namespace
531551
-children will have a set of PID to process mappings separate from the
531551
+Children will have a set of PID to process mappings separate from the
531551
 .B nsenter
531551
 process
531551
 .RB ( CLONE_\:NEWPID
531551
@@ -46,18 +47,18 @@ flag).
531551
 .B nsenter
531551
 will fork by default if changing the PID namespace, so that the new program
531551
 and its children share the same PID namespace and are visible to each other.
531551
-If \-\-no\-fork is used, the new program will be exec'ed without forking.
531551
-.PP
531551
-See the
531551
-.BR clone (2)
531551
-for exact semantics of the flags.
531551
+If \fB\-\-no\-fork\fP is used, the new program will be exec'ed without forking.
531551
 .TP
531551
-If program is not given, run ``${SHELL}'' (default: /bin\:/sh).
531551
+.B user namespace
531551
+The process will have a distinct set of UIDs, GIDs and capabilities.
531551
+.RB ( CLONE_\:NEWUSER
531551
+flag)
531551
+.TP
531551
+See \fBclone\fP(2) for the exact semantics of the flags.
531551
+.TP
531551
+If \fIprogram\fP is not given, then ``${SHELL}'' is run (default: /bin\:/sh).
531551
 
531551
 .SH OPTIONS
531551
-Argument with square brakets, such as [\fIfile\fR], means optional argument.
531551
-Command line syntax to specify optional argument \-\-mount=/path\:/to\:/file.
531551
-Please notice the equals sign.
531551
 .TP
531551
 \fB\-t\fR, \fB\-\-target\fR \fIpid\fP
531551
 Specify a target process to get contexts from.  The paths to the contexts
531551
@@ -83,6 +84,9 @@ the network namespace
531551
 /proc/\fIpid\fR/ns/pid
531551
 the PID namespace
531551
 .TP
531551
+/proc/\fIpid\fR/ns/user
531551
+the user namespace
531551
+.TP
531551
 /proc/\fIpid\fR/root
531551
 the root directory
531551
 .TP
531551
@@ -91,51 +95,71 @@ the working directory respectively
531551
 .PD
531551
 .RE
531551
 .TP
531551
-\fB\-m\fR, \fB\-\-mount\fR [\fIfile\fR]
531551
-Enter the mount namespace.  If no file is specified enter the mount namespace
531551
-of the target process.  If file is specified enter the mount namespace
531551
+\fB\-m\fR, \fB\-\-mount\fR[=\fIfile\fR]
531551
+Enter the mount namespace.  If no file is specified, enter the mount namespace
531551
+of the target process.  If file is specified, enter the mount namespace
531551
 specified by file.
531551
 .TP
531551
-\fB\-u\fR, \fB\-\-uts\fR [\fIfile\fR]
531551
-Enter the UTS namespace.  If no file is specified enter the UTS namespace of
531551
-the target process.  If file is specified enter the UTS namespace specified by
531551
+\fB\-u\fR, \fB\-\-uts\fR[=\fIfile\fR]
531551
+Enter the UTS namespace.  If no file is specified, enter the UTS namespace of
531551
+the target process.  If file is specified, enter the UTS namespace specified by
531551
 file.
531551
 .TP
531551
-\fB\-i\fR, \fB\-\-ipc\fR [\fIfile\fR]
531551
-Enter the IPC namespace.  If no file is specified enter the IPC namespace of
531551
-the target process.  If file is specified enter the IPC namespace specified by
531551
+\fB\-i\fR, \fB\-\-ipc\fR[=\fIfile\fR]
531551
+Enter the IPC namespace.  If no file is specified, enter the IPC namespace of
531551
+the target process.  If file is specified, enter the IPC namespace specified by
531551
 file.
531551
 .TP
531551
-\fB\-n\fR, \fB\-\-net\fR [\fIfile\fR]
531551
-Enter the network namespace.  If no file is specified enter the network
531551
-namespace of the target process.  If file is specified enter the network
531551
+\fB\-n\fR, \fB\-\-net\fR[=\fIfile\fR]
531551
+Enter the network namespace.  If no file is specified, enter the network
531551
+namespace of the target process.  If file is specified, enter the network
531551
 namespace specified by file.
531551
 .TP
531551
-\fB\-p\fR, \fB\-\-pid\fR [\fIfile\fR]
531551
-Enter the PID namespace.  If no file is specified enter the PID namespace of
531551
-the target process.  If file is specified enter the PID namespace specified by
531551
+\fB\-p\fR, \fB\-\-pid\fR[=\fIfile\fR]
531551
+Enter the PID namespace.  If no file is specified, enter the PID namespace of
531551
+the target process.  If file is specified, enter the PID namespace specified by
531551
 file.
531551
 .TP
531551
-\fB\-r\fR, \fB\-\-root\fR [\fIdirectory\fR]
531551
-Set the root directory.  If no directory is specified set the root directory to
531551
-the root directory of the target process.  If directory is specified set the
531551
+\fB\-U\fR, \fB\-\-user\fR[=\fIfile\fR]
531551
+Enter the user namespace.  If no file is specified, enter the user namespace of
531551
+the target process.  If file is specified, enter the user namespace specified by
531551
+file.  See also the \fB\-\-setuid\fR and \fB\-\-setgid\fR options.
531551
+.TP
531551
+\fB\-G\fR, \fB\-\-setgid\fR \fIgid\fR
531551
+Set the group ID which will be used in the entered namespace and drop
531551
+supplementary groups.
531551
+.BR nsenter (1)
531551
+always sets GID for user namespaces, the default is 0.
531551
+.TP
531551
+\fB\-S\fR, \fB\-\-setuid\fR \fIuid\fR
531551
+Set the user ID which will be used in the entered namespace.
531551
+.BR nsenter (1)
531551
+always sets UID for user namespaces, the default is 0.
531551
+.TP
531551
+\fB\-\-preserve\-credentials\fR
531551
+Don't modify UID and GID when enter user namespace. The default is to
531551
+drops supplementary groups and sets GID and UID to 0.
531551
+.TP
531551
+\fB\-r\fR, \fB\-\-root\fR[=\fIdirectory\fR]
531551
+Set the root directory.  If no directory is specified, set the root directory to
531551
+the root directory of the target process.  If directory is specified, set the
531551
 root directory to the specified directory.
531551
 .TP
531551
-\fB\-w\fR, \fB\-\-wd\fR [\fIdirectory\fR]
531551
-Set the working directory.  If no directory is specified set the working
531551
+\fB\-w\fR, \fB\-\-wd\fR[=\fIdirectory\fR]
531551
+Set the working directory.  If no directory is specified, set the working
531551
 directory to the working directory of the target process.  If directory is
531551
-specified set the working directory to the specified directory.
531551
+specified, set the working directory to the specified directory.
531551
 .TP
531551
-\fB\-F\fR, \fB\-\-no-fork\fR
531551
-Do not fork before exec'ing the specified program.  By default when entering a
531551
-pid namespace enter calls fork before calling exec so that the children will be
531551
-in the newly entered pid namespace.
531551
+\fB\-F\fR, \fB\-\-no\-fork\fR
531551
+Do not fork before exec'ing the specified program.  By default, when entering a
531551
+PID namespace, \fBnsenter\fP calls \fBfork\fP before calling \fBexec\fP so that
531551
+any children will also be in the newly entered PID namespace.
531551
 .TP
531551
 \fB\-V\fR, \fB\-\-version\fR
531551
 Display version information and exit.
531551
 .TP
531551
 \fB\-h\fR, \fB\-\-help\fR
531551
-Print a help message.
531551
+Display help text and exit.
531551
 .SH SEE ALSO
531551
 .BR setns (2),
531551
 .BR clone (2)
531551
diff -up util-linux-2.23.2/sys-utils/nsenter.c.kzak util-linux-2.23.2/sys-utils/nsenter.c
531551
--- util-linux-2.23.2/sys-utils/nsenter.c.kzak	2015-06-26 09:58:39.468633643 +0200
531551
+++ util-linux-2.23.2/sys-utils/nsenter.c	2015-06-26 09:58:51.673541033 +0200
531551
@@ -28,6 +28,7 @@
531551
 #include <assert.h>
531551
 #include <sys/types.h>
531551
 #include <sys/wait.h>
531551
+#include <grp.h>
531551
 
531551
 #include "strutils.h"
531551
 #include "nls.h"
531551
@@ -42,7 +43,12 @@ static struct namespace_file {
531551
 	int fd;
531551
 } namespace_files[] = {
531551
 	/* Careful the order is significant in this array.
531551
+	 *
531551
+	 * The user namespace comes first, so that it is entered
531551
+	 * first.  This gives an unprivileged user the potential to
531551
+	 * enter the other namespaces.
531551
 	 */
531551
+	{ .nstype = CLONE_NEWUSER, .name = "ns/user", .fd = -1 },
531551
 	{ .nstype = CLONE_NEWIPC,  .name = "ns/ipc",  .fd = -1 },
531551
 	{ .nstype = CLONE_NEWUTS,  .name = "ns/uts",  .fd = -1 },
531551
 	{ .nstype = CLONE_NEWNET,  .name = "ns/net",  .fd = -1 },
531551
@@ -56,18 +62,25 @@ static void usage(int status)
531551
 	FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
531551
 
531551
 	fputs(USAGE_HEADER, out);
531551
-	fprintf(out, _(" %s [options] <program> [args...]\n"),
531551
+	fprintf(out, _(" %s [options] <program> [<argument>...]\n"),
531551
 		program_invocation_short_name);
531551
 
531551
+	fputs(USAGE_SEPARATOR, out);
531551
+	fputs(_("Run a program with namespaces of other processes.\n"), out);
531551
+
531551
 	fputs(USAGE_OPTIONS, out);
531551
 	fputs(_(" -t, --target <pid>     target process to get namespaces from\n"), out);
531551
-	fputs(_(" -m, --mount [=<file>]  enter mount namespace\n"), out);
531551
-	fputs(_(" -u, --uts   [=<file>]  enter UTS namespace (hostname etc)\n"), out);
531551
-	fputs(_(" -i, --ipc   [=<file>]  enter System V IPC namespace\n"), out);
531551
-	fputs(_(" -n, --net   [=<file>]  enter network namespace\n"), out);
531551
-	fputs(_(" -p, --pid   [=<file>]  enter pid namespace\n"), out);
531551
-	fputs(_(" -r, --root  [=<dir>]   set the root directory\n"), out);
531551
-	fputs(_(" -w, --wd    [=<dir>]   set the working directory\n"), out);
531551
+	fputs(_(" -m, --mount[=<file>]   enter mount namespace\n"), out);
531551
+	fputs(_(" -u, --uts[=<file>]     enter UTS namespace (hostname etc)\n"), out);
531551
+	fputs(_(" -i, --ipc[=<file>]     enter System V IPC namespace\n"), out);
531551
+	fputs(_(" -n, --net[=<file>]     enter network namespace\n"), out);
531551
+	fputs(_(" -p, --pid[=<file>]     enter pid namespace\n"), out);
531551
+	fputs(_(" -U, --user[=<file>]    enter user namespace\n"), out);
531551
+	fputs(_(" -S, --setuid <uid>     set uid in entered namespace\n"), out);
531551
+	fputs(_(" -G, --setgid <gid>     set gid in entered namespace\n"), out);
531551
+	fputs(_("     --preserve-credentials do not touch uids or gids\n"), out);
531551
+	fputs(_(" -r, --root[=<dir>]     set the root directory\n"), out);
531551
+	fputs(_(" -w, --wd[=<dir>]       set the working directory\n"), out);
531551
 	fputs(_(" -F, --no-fork          do not fork before exec'ing <program>\n"), out);
531551
 
531551
 	fputs(USAGE_SEPARATOR, out);
531551
@@ -153,6 +166,9 @@ static void continue_as_child(void)
531551
 
531551
 int main(int argc, char *argv[])
531551
 {
531551
+	enum {
531551
+		OPT_PRESERVE_CRED = CHAR_MAX + 1
531551
+	};
531551
 	static const struct option longopts[] = {
531551
 		{ "help", no_argument, NULL, 'h' },
531551
 		{ "version", no_argument, NULL, 'V'},
531551
@@ -162,24 +178,30 @@ int main(int argc, char *argv[])
531551
 		{ "ipc", optional_argument, NULL, 'i' },
531551
 		{ "net", optional_argument, NULL, 'n' },
531551
 		{ "pid", optional_argument, NULL, 'p' },
531551
+		{ "user", optional_argument, NULL, 'U' },
531551
+		{ "setuid", required_argument, NULL, 'S' },
531551
+		{ "setgid", required_argument, NULL, 'G' },
531551
 		{ "root", optional_argument, NULL, 'r' },
531551
 		{ "wd", optional_argument, NULL, 'w' },
531551
 		{ "no-fork", no_argument, NULL, 'F' },
531551
+		{ "preserve-credentials", no_argument, NULL, OPT_PRESERVE_CRED },
531551
 		{ NULL, 0, NULL, 0 }
531551
 	};
531551
 
531551
 	struct namespace_file *nsfile;
531551
-	int c, namespaces = 0;
531551
-	bool do_rd = false, do_wd = false;
531551
+	int c, namespaces = 0, setgroups_nerrs = 0, preserve_cred = 0;
531551
+	bool do_rd = false, do_wd = false, force_uid = false, force_gid = false;
531551
 	int do_fork = -1; /* unknown yet */
531551
+	uid_t uid = 0;
531551
+	gid_t gid = 0;
531551
 
531551
-	setlocale(LC_MESSAGES, "");
531551
+	setlocale(LC_ALL, "");
531551
 	bindtextdomain(PACKAGE, LOCALEDIR);
531551
 	textdomain(PACKAGE);
531551
 	atexit(close_stdout);
531551
 
531551
 	while ((c =
531551
-		getopt_long(argc, argv, "hVt:m::u::i::n::p::r::w::F",
531551
+		getopt_long(argc, argv, "+hVt:m::u::i::n::p::U::S:G:r::w::F",
531551
 			    longopts, NULL)) != -1) {
531551
 		switch (c) {
531551
 		case 'h':
531551
@@ -221,6 +243,20 @@ int main(int argc, char *argv[])
531551
 			else
531551
 				namespaces |= CLONE_NEWPID;
531551
 			break;
531551
+		case 'U':
531551
+			if (optarg)
531551
+				open_namespace_fd(CLONE_NEWUSER, optarg);
531551
+			else
531551
+				namespaces |= CLONE_NEWUSER;
531551
+			break;
531551
+		case 'S':
531551
+			uid = strtoul_or_err(optarg, _("failed to parse uid"));
531551
+			force_uid = true;
531551
+			break;
531551
+		case 'G':
531551
+			gid = strtoul_or_err(optarg, _("failed to parse gid"));
531551
+			force_gid = true;
531551
+			break;
531551
 		case 'F':
531551
 			do_fork = 0;
531551
 			break;
531551
@@ -236,6 +272,9 @@ int main(int argc, char *argv[])
531551
 			else
531551
 				do_wd = true;
531551
 			break;
531551
+		case OPT_PRESERVE_CRED:
531551
+			preserve_cred = 1;
531551
+			break;
531551
 		default:
531551
 			usage(EXIT_FAILURE);
531551
 		}
531551
@@ -253,6 +292,26 @@ int main(int argc, char *argv[])
531551
 		open_target_fd(&wd_fd, "cwd", NULL);
531551
 
531551
 	/*
531551
+	 * Update namespaces variable to contain all requested namespaces
531551
+	 */
531551
+	for (nsfile = namespace_files; nsfile->nstype; nsfile++) {
531551
+		if (nsfile->fd < 0)
531551
+			continue;
531551
+		namespaces |= nsfile->nstype;
531551
+	}
531551
+
531551
+	/* for user namespaces we always set UID and GID (default is 0)
531551
+	 * and clear root's groups if --preserve-credentials is no specified */
531551
+	if ((namespaces & CLONE_NEWUSER) && !preserve_cred) {
531551
+		force_uid = true, force_gid = true;
531551
+
531551
+		/* We call setgroups() before and after we enter user namespace,
531551
+		 * let's complain only if both fail */
531551
+		if (setgroups(0, NULL) != 0)
531551
+			setgroups_nerrs++;
531551
+	}
531551
+
531551
+	/*
531551
 	 * Now that we know which namespaces we want to enter, enter them.
531551
 	 */
531551
 	for (nsfile = namespace_files; nsfile->nstype; nsfile++) {
531551
@@ -302,6 +361,15 @@ int main(int argc, char *argv[])
531551
 	if (do_fork == 1)
531551
 		continue_as_child();
531551
 
531551
+	if (force_uid || force_gid) {
531551
+		if (force_gid && setgroups(0, NULL) != 0 && setgroups_nerrs)	/* drop supplementary groups */
531551
+			err(EXIT_FAILURE, _("setgroups failed"));
531551
+		if (force_gid && setgid(gid) < 0)		/* change GID */
531551
+			err(EXIT_FAILURE, _("setgid failed"));
531551
+		if (force_uid && setuid(uid) < 0)		/* change UID */
531551
+			err(EXIT_FAILURE, _("setuid failed"));
531551
+	}
531551
+
531551
 	if (optind < argc) {
531551
 		execvp(argv[optind], argv + optind);
531551
 		err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]);
531551
diff -up util-linux-2.23.2/sys-utils/unshare.1.kzak util-linux-2.23.2/sys-utils/unshare.1
531551
--- util-linux-2.23.2/sys-utils/unshare.1.kzak	2015-06-26 09:58:39.484633521 +0200
531551
+++ util-linux-2.23.2/sys-utils/unshare.1	2015-06-26 09:58:51.673541033 +0200
531551
@@ -1,28 +1,27 @@
531551
-.\" Process this file with
531551
-.\" groff -man -Tascii lscpu.1
531551
-.\"
531551
-.TH UNSHARE 1 "July 2013" "util-linux" "User Commands"
531551
+.TH UNSHARE 1 "July 2014" "util-linux" "User Commands"
531551
 .SH NAME
531551
 unshare \- run program with some namespaces unshared from parent
531551
 .SH SYNOPSIS
531551
 .B unshare
531551
-.RI [ options ]
531551
+[options]
531551
 .I program
531551
 .RI [ arguments ]
531551
 .SH DESCRIPTION
531551
 Unshares the indicated namespaces from the parent process and then executes
531551
-the specified program.  The namespaces to be unshared are indicated via
531551
+the specified \fIprogram\fR.  The namespaces to be unshared are indicated via
531551
 options.  Unshareable namespaces are:
531551
 .TP
531551
 .BR "mount namespace"
531551
 Mounting and unmounting filesystems will not affect the rest of the system
531551
 (\fBCLONE_NEWNS\fP flag), except for filesystems which are explicitly marked as
531551
-shared (with \fBmount --make-shared\fP; see \fI/proc/self/mountinfo\fP for the
531551
-\fBshared\fP flags).
531551
-
531551
-It's recommended to use \fBmount --make-rprivate\fP or \fBmount --make-rslave\fP
531551
-after \fBunshare --mount\fP to make sure that mountpoints in the new namespace
531551
-are really unshared from parental namespace.
531551
+shared (with \fBmount --make-shared\fP; see \fI/proc/self/mountinfo\fP or
531551
+\fBfindmnt -o+PROPAGATION\fP for the \fBshared\fP flags).
531551
+.sp
531551
+.B unshare
531551
+automatically sets propagation to \fBprivate\fP
531551
+in the new mount namespace to make sure that the new namespace is really
531551
+unshared. This feature is possible to disable by option \fB\-\-propagation unchanged\fP.
531551
+Note that \fBprivate\fP is the kernel default.
531551
 .TP
531551
 .BR "UTS namespace"
531551
 Setting hostname or domainname will not affect the rest of the system.
531551
@@ -40,13 +39,14 @@ sockets, etc.  (\fBCLONE_NEWNET\fP flag)
531551
 .BR "pid namespace"
531551
 Children will have a distinct set of PID to process mappings from their parent.
531551
 (\fBCLONE_NEWPID\fP flag)
531551
+.TP
531551
+.BR "user namespace"
531551
+The process will have a distinct set of UIDs, GIDs and capabilities.
531551
+(\fBCLONE_NEWUSER\fP flag)
531551
 .PP
531551
 See \fBclone\fR(2) for the exact semantics of the flags.
531551
 .SH OPTIONS
531551
 .TP
531551
-.BR \-h , " \-\-help"
531551
-Display help text and exit.
531551
-.TP
531551
 .BR \-i , " \-\-ipc"
531551
 Unshare the IPC namespace.
531551
 .TP
531551
@@ -63,16 +63,68 @@ See also the \fB--fork\fP and \fB--mount
531551
 .BR \-u , " \-\-uts"
531551
 Unshare the UTS namespace.
531551
 .TP
531551
+.BR \-U , " \-\-user"
531551
+Unshare the user namespace.
531551
+.TP
531551
 .BR \-f , " \-\-fork"
531551
 Fork the specified \fIprogram\fR as a child process of \fBunshare\fR rather than
531551
 running it directly.  This is useful when creating a new pid namespace.
531551
 .TP
531551
-.BR \-\-mount-proc "[=\fImountpoint\fP]"
531551
-Just before running the program, mount the proc filesystem at the \fImountpoint\fP
531551
+.BR \-\-mount\-proc "[=\fImountpoint\fP]"
531551
+Just before running the program, mount the proc filesystem at \fImountpoint\fP
531551
 (default is /proc).  This is useful when creating a new pid namespace.  It also
531551
 implies creating a new mount namespace since the /proc mount would otherwise
531551
-mess up existing programs on the system. The new proc filesystem is explicitly
531551
+mess up existing programs on the system.  The new proc filesystem is explicitly
531551
 mounted as private (by MS_PRIVATE|MS_REC).
531551
+.TP
531551
+.BR \-r , " \-\-map\-root\-user"
531551
+Run the program only after the current effective user and group IDs have been mapped to
531551
+the superuser UID and GID in the newly created user namespace.  This makes it possible to
531551
+conveniently gain capabilities needed to manage various aspects of the newly created
531551
+namespaces (such as configuring interfaces in the network namespace or mounting filesystems in
531551
+the mount namespace) even when run unprivileged.  As a mere convenience feature, it does not support
531551
+more sophisticated use cases, such as mapping multiple ranges of UIDs and GIDs.
531551
+This option implies --setgroups=deny.
531551
+.TP
531551
+.BR "\-\-propagation \fIprivate|shared|slave|unchanged\fP"
531551
+Recursively sets mount propagation flag in the new mount namespace. The default
531551
+is to set the propagation to \fIprivate\fP, this feature is possible to disable
531551
+by \fIunchanged\fP argument. The options is silently ignored when mount namespace (\fB\-\-mount\fP)
531551
+is not requested.
531551
+.TP
531551
+.BR "\-\-setgroups \fIallow|deny\fP"
531551
+Allow or deny
531551
+.BR setgroups (2)
531551
+syscall in user namespaces.
531551
+
531551
+.BR setgroups(2)
531551
+is only callable with CAP_SETGID and CAP_SETGID in a user
531551
+namespace (since Linux 3.19) does not give you permission to call setgroups(2)
531551
+until after GID map has been set. The GID map is writable by root when
531551
+.BR setgroups(2)
531551
+is enabled and GID map becomes writable by unprivileged processes when
531551
+.BR setgroups(2)
531551
+is permanently disabled.
531551
+.TP
531551
+.BR \-V , " \-\-version"
531551
+Display version information and exit.
531551
+.TP
531551
+.BR \-h , " \-\-help"
531551
+Display help text and exit.
531551
+.SH EXAMPLES
531551
+.TP
531551
+.B # unshare --fork --pid --mount-proc readlink /proc/self
531551
+.TQ
531551
+1
531551
+.br
531551
+Establish a PID namespace, ensure we're PID 1 in it against newly mounted
531551
+procfs instance.
531551
+.TP
531551
+.B $ unshare --map-root-user --user sh -c whoami
531551
+.TQ
531551
+root
531551
+.br
531551
+Establish a user namespace as an unprivileged user with a root user within it.
531551
 .SH SEE ALSO
531551
 .BR unshare (2),
531551
 .BR clone (2),
531551
diff -up util-linux-2.23.2/sys-utils/unshare.c.kzak util-linux-2.23.2/sys-utils/unshare.c
531551
--- util-linux-2.23.2/sys-utils/unshare.c.kzak	2015-06-26 09:58:39.484633521 +0200
531551
+++ util-linux-2.23.2/sys-utils/unshare.c	2015-06-26 09:58:51.673541033 +0200
531551
@@ -32,19 +32,117 @@
531551
 
531551
 #include "nls.h"
531551
 #include "c.h"
531551
+#include "closestream.h"
531551
 #include "namespace.h"
531551
 #include "exec_shell.h"
531551
 #include "xalloc.h"
531551
 #include "pathnames.h"
531551
+#include "all-io.h"
531551
 
531551
+/* 'private' is kernel default */
531551
+#define UNSHARE_PROPAGATION_DEFAULT	(MS_REC | MS_PRIVATE)
531551
+
531551
+enum {
531551
+	SETGROUPS_NONE = -1,
531551
+	SETGROUPS_DENY = 0,
531551
+	SETGROUPS_ALLOW = 1,
531551
+};
531551
+
531551
+static const char *setgroups_strings[] =
531551
+{
531551
+	[SETGROUPS_DENY] = "deny",
531551
+	[SETGROUPS_ALLOW] = "allow"
531551
+};
531551
+
531551
+static int setgroups_str2id(const char *str)
531551
+{
531551
+	size_t i;
531551
+
531551
+	for (i = 0; i < ARRAY_SIZE(setgroups_strings); i++)
531551
+		if (strcmp(str, setgroups_strings[i]) == 0)
531551
+			return i;
531551
+
531551
+	errx(EXIT_FAILURE, _("unsupported --setgroups argument '%s'"), str);
531551
+}
531551
+
531551
+static void setgroups_control(int action)
531551
+{
531551
+	const char *file = _PATH_PROC_SETGROUPS;
531551
+	const char *cmd;
531551
+	int fd;
531551
+
531551
+	if (action < 0 || (size_t) action >= ARRAY_SIZE(setgroups_strings))
531551
+		return;
531551
+	cmd = setgroups_strings[action];
531551
+
531551
+	fd = open(file, O_WRONLY);
531551
+	if (fd < 0) {
531551
+		if (errno == ENOENT)
531551
+			return;
531551
+		 err(EXIT_FAILURE, _("cannot open %s"), file);
531551
+	}
531551
+
531551
+	if (write_all(fd, cmd, strlen(cmd)))
531551
+		err(EXIT_FAILURE, _("write failed %s"), file);
531551
+	close(fd);
531551
+}
531551
+
531551
+static void map_id(const char *file, uint32_t from, uint32_t to)
531551
+{
531551
+	char *buf;
531551
+	int fd;
531551
+
531551
+	fd = open(file, O_WRONLY);
531551
+	if (fd < 0)
531551
+		 err(EXIT_FAILURE, _("cannot open %s"), file);
531551
+
531551
+	xasprintf(&buf, "%u %u 1", from, to);
531551
+	if (write_all(fd, buf, strlen(buf)))
531551
+		err(EXIT_FAILURE, _("write failed %s"), file);
531551
+	free(buf);
531551
+	close(fd);
531551
+}
531551
+
531551
+static unsigned long parse_propagation(const char *str)
531551
+{
531551
+	size_t i;
531551
+	static const struct prop_opts {
531551
+		const char *name;
531551
+		unsigned long flag;
531551
+	} opts[] = {
531551
+		{ "slave",	MS_REC | MS_SLAVE },
531551
+		{ "private",	MS_REC | MS_PRIVATE },
531551
+		{ "shared",     MS_REC | MS_SHARED },
531551
+		{ "unchanged",        0 }
531551
+	};
531551
+
531551
+	for (i = 0; i < ARRAY_SIZE(opts); i++) {
531551
+		if (strcmp(opts[i].name, str) == 0)
531551
+			return opts[i].flag;
531551
+	}
531551
+
531551
+	errx(EXIT_FAILURE, _("unsupported propagation mode: %s"), str);
531551
+}
531551
+
531551
+static void set_propagation(unsigned long flags)
531551
+{
531551
+	if (flags == 0)
531551
+		return;
531551
+
531551
+	if (mount("none", "/", NULL, flags, NULL) != 0)
531551
+		err(EXIT_FAILURE, _("cannot change root filesystem propagation"));
531551
+}
531551
 
531551
 static void usage(int status)
531551
 {
531551
 	FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
531551
 
531551
 	fputs(USAGE_HEADER, out);
531551
-	fprintf(out,
531551
-	      _(" %s [options] <program> [args...]\n"),	program_invocation_short_name);
531551
+	fprintf(out, _(" %s [options] <program> [<argument>...]\n"),
531551
+		program_invocation_short_name);
531551
+
531551
+	fputs(USAGE_SEPARATOR, out);
531551
+	fputs(_("Run a program with some namespaces unshared from the parent.\n"), out);
531551
 
531551
 	fputs(USAGE_OPTIONS, out);
531551
 	fputs(_(" -m, --mount               unshare mounts namespace\n"), out);
531551
@@ -52,8 +150,13 @@ static void usage(int status)
531551
 	fputs(_(" -i, --ipc                 unshare System V IPC namespace\n"), out);
531551
 	fputs(_(" -n, --net                 unshare network namespace\n"), out);
531551
 	fputs(_(" -p, --pid                 unshare pid namespace\n"), out);
531551
+	fputs(_(" -U, --user                unshare user namespace\n"), out);
531551
 	fputs(_(" -f, --fork                fork before launching <program>\n"), out);
531551
 	fputs(_("     --mount-proc[=<dir>]  mount proc filesystem first (implies --mount)\n"), out);
531551
+	fputs(_(" -r, --map-root-user       map current user to root (implies --user)\n"), out);
531551
+	fputs(_("     --propagation <slave|shared|private|unchanged>\n"
531551
+	        "                           modify mount propagation in mount namespace\n"), out);
531551
+	fputs(_(" -s, --setgroups allow|deny  control the setgroups syscall in user namespaces\n"), out);
531551
 
531551
 	fputs(USAGE_SEPARATOR, out);
531551
 	fputs(USAGE_HELP, out);
531551
@@ -66,7 +169,9 @@ static void usage(int status)
531551
 int main(int argc, char *argv[])
531551
 {
531551
 	enum {
531551
-		OPT_MOUNTPROC = CHAR_MAX + 1
531551
+		OPT_MOUNTPROC = CHAR_MAX + 1,
531551
+		OPT_PROPAGATION,
531551
+		OPT_SETGROUPS
531551
 	};
531551
 	static const struct option longopts[] = {
531551
 		{ "help", no_argument, 0, 'h' },
531551
@@ -76,20 +181,29 @@ int main(int argc, char *argv[])
531551
 		{ "ipc", no_argument, 0, 'i' },
531551
 		{ "net", no_argument, 0, 'n' },
531551
 		{ "pid", no_argument, 0, 'p' },
531551
+		{ "user", no_argument, 0, 'U' },
531551
 		{ "fork", no_argument, 0, 'f' },
531551
 		{ "mount-proc", optional_argument, 0, OPT_MOUNTPROC },
531551
+		{ "map-root-user", no_argument, 0, 'r' },
531551
+		{ "propagation", required_argument, 0, OPT_PROPAGATION },
531551
+		{ "setgroups", required_argument, 0, OPT_SETGROUPS },
531551
 		{ NULL, 0, 0, 0 }
531551
 	};
531551
 
531551
+	int setgrpcmd = SETGROUPS_NONE;
531551
 	int unshare_flags = 0;
531551
-	int c, forkit = 0;
531551
+	int c, forkit = 0, maproot = 0;
531551
 	const char *procmnt = NULL;
531551
+	unsigned long propagation = UNSHARE_PROPAGATION_DEFAULT;
531551
+	uid_t real_euid = geteuid();
531551
+	gid_t real_egid = getegid();;
531551
 
531551
 	setlocale(LC_ALL, "");
531551
 	bindtextdomain(PACKAGE, LOCALEDIR);
531551
 	textdomain(PACKAGE);
531551
+	atexit(close_stdout);
531551
 
531551
-	while ((c = getopt_long(argc, argv, "+fhVmuinp", longopts, NULL)) != -1) {
531551
+	while ((c = getopt_long(argc, argv, "+fhVmuinpUr", longopts, NULL)) != -1) {
531551
 		switch (c) {
531551
 		case 'f':
531551
 			forkit = 1;
531551
@@ -114,10 +228,23 @@ int main(int argc, char *argv[])
531551
 		case 'p':
531551
 			unshare_flags |= CLONE_NEWPID;
531551
 			break;
531551
+		case 'U':
531551
+			unshare_flags |= CLONE_NEWUSER;
531551
+			break;
531551
 		case OPT_MOUNTPROC:
531551
 			unshare_flags |= CLONE_NEWNS;
531551
 			procmnt = optarg ? optarg : "/proc";
531551
 			break;
531551
+		case 'r':
531551
+			unshare_flags |= CLONE_NEWUSER;
531551
+			maproot = 1;
531551
+			break;
531551
+		case OPT_SETGROUPS:
531551
+			setgrpcmd = setgroups_str2id(optarg);
531551
+			break;
531551
+		case OPT_PROPAGATION:
531551
+			propagation = parse_propagation(optarg);
531551
+			break;
531551
 		default:
531551
 			usage(EXIT_FAILURE);
531551
 		}
531551
@@ -146,6 +273,25 @@ int main(int argc, char *argv[])
531551
 		}
531551
 	}
531551
 
531551
+	if (maproot) {
531551
+		if (setgrpcmd == SETGROUPS_ALLOW)
531551
+			errx(EXIT_FAILURE, _("options --setgroups=allow and "
531551
+					"--map-root-user are mutually exclusive"));
531551
+
531551
+		/* since Linux 3.19 unprivileged writing of /proc/self/gid_map
531551
+		 * has s been disabled unless /proc/self/setgroups is written
531551
+		 * first to permanently disable the ability to call setgroups
531551
+		 * in that user namespace. */
531551
+		setgroups_control(SETGROUPS_DENY);
531551
+		map_id(_PATH_PROC_UIDMAP, 0, real_euid);
531551
+		map_id(_PATH_PROC_GIDMAP, 0, real_egid);
531551
+
531551
+	} else if (setgrpcmd != SETGROUPS_NONE)
531551
+		setgroups_control(setgrpcmd);
531551
+
531551
+	if ((unshare_flags & CLONE_NEWNS) && propagation)
531551
+		set_propagation(propagation);
531551
+
531551
 	if (procmnt &&
531551
 	    (mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL) != 0 ||
531551
 	     mount("proc", procmnt, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0))