.BR "mount namespace"
Mounting and unmounting filesystems will not affect the rest of the system
(\fBCLONE_NEWNS\fP flag), except for filesystems which are explicitly marked as
-shared (with \fBmount --make-shared\fP; see \fI/proc/self/mountinfo\fP for the
-\fBshared\fP flags).
+shared (with \fBmount --make-shared\fP; see \fI/proc/self/mountinfo\fP or
+\fBfindmnt -o+PROPAGATION\fP for the \fBshared\fP flags).
.sp
-It's recommended to use \fBmount --make-rprivate\fP or \fBmount --make-rslave\fP
-after \fBunshare --mount\fP to make sure that mountpoints in the new namespace
-are really unshared from the parental namespace.
+.B unshare
+since util-linux version 2.27 automatically sets propagation to \fBprivate\fP
+in the new mount namespace to make sure that the new namespace is really
+unshared. This feature is possible to disable by option \fB\-\-propagation unchanged\fP.
+Note that \fBprivate\fP is the kernel default.
.TP
.BR "UTS namespace"
Setting hostname or domainname will not affect the rest of the system.
more sophisticated use cases, such as mapping multiple ranges of UIDs and GIDs.
This option implies --setgroups=deny.
.TP
-.BR \-s , " \-\-setgroups \fIallow|deny\fP"
+.BR "\-\-propagation \fIprivate|shared|slave|unchanged\fP"
+Recursively sets mount propagation flag in the new mount namespace. The default
+is to set the propagation to \fIprivate\fP, this feature is possible to disable
+by \fIunchanged\fP argument. The options is silently ignored when mount namespace (\fB\-\-mount\fP)
+is not requested.
+.TP
+.BR "\-\-setgroups \fIallow|deny\fP"
Allow or deny
.BR setgroups (2)
syscall in user namespaces.
#include "pathnames.h"
#include "all-io.h"
+/* 'private' is kernel default */
+#define UNSHARE_PROPAGATION_DEFAULT (MS_REC | MS_PRIVATE)
+
enum {
SETGROUPS_NONE = -1,
SETGROUPS_DENY = 0,
close(fd);
}
+static unsigned long parse_propagation(const char *str)
+{
+ size_t i;
+ static const struct prop_opts {
+ const char *name;
+ unsigned long flag;
+ } opts[] = {
+ { "slave", MS_REC | MS_SLAVE },
+ { "private", MS_REC | MS_PRIVATE },
+ { "shared", MS_REC | MS_SHARED },
+ { "unchanged", 0 }
+ };
+
+ for (i = 0; i < ARRAY_SIZE(opts); i++) {
+ if (strcmp(opts[i].name, str) == 0)
+ return opts[i].flag;
+ }
+
+ errx(EXIT_FAILURE, _("unsupported propagation mode: %s"), str);
+}
+
+static void set_propagation(unsigned long flags)
+{
+ if (flags == 0)
+ return;
+
+ if (mount("none", "/", NULL, flags, NULL) != 0)
+ err(EXIT_FAILURE, _("cannot change root filesystem propagation"));
+}
+
static void usage(int status)
{
FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
fputs(_(" -f, --fork fork before launching <program>\n"), out);
fputs(_(" --mount-proc[=<dir>] mount proc filesystem first (implies --mount)\n"), out);
fputs(_(" -r, --map-root-user map current user to root (implies --user)\n"), out);
+ fputs(_(" --propagation <slave|shared|private|unchanged>\n"
+ " modify mount propagation in mount namespace\n"), out);
fputs(_(" -s, --setgroups allow|deny control the setgroups syscall in user namespaces\n"), out);
fputs(USAGE_SEPARATOR, out);
{
enum {
OPT_MOUNTPROC = CHAR_MAX + 1,
+ OPT_PROPAGATION,
OPT_SETGROUPS
};
static const struct option longopts[] = {
{ "fork", no_argument, 0, 'f' },
{ "mount-proc", optional_argument, 0, OPT_MOUNTPROC },
{ "map-root-user", no_argument, 0, 'r' },
+ { "propagation", required_argument, 0, OPT_PROPAGATION },
{ "setgroups", required_argument, 0, OPT_SETGROUPS },
{ NULL, 0, 0, 0 }
};
int unshare_flags = 0;
int c, forkit = 0, maproot = 0;
const char *procmnt = NULL;
+ unsigned long propagation = UNSHARE_PROPAGATION_DEFAULT;
uid_t real_euid = geteuid();
gid_t real_egid = getegid();;
case OPT_SETGROUPS:
setgrpcmd = setgroups_str2id(optarg);
break;
+ case OPT_PROPAGATION:
+ propagation = parse_propagation(optarg);
+ break;
default:
usage(EXIT_FAILURE);
}
} else if (setgrpcmd != SETGROUPS_NONE)
setgroups_control(setgrpcmd);
+ if ((unshare_flags & CLONE_NEWNS) && propagation)
+ set_propagation(propagation);
+
if (procmnt &&
(mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL) != 0 ||
mount("proc", procmnt, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0))