summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/namespace.h3
-rw-r--r--sys-utils/nsenter.114
-rw-r--r--sys-utils/nsenter.c23
-rw-r--r--sys-utils/unshare.19
-rw-r--r--sys-utils/unshare.c34
5 files changed, 63 insertions, 20 deletions
diff --git a/include/namespace.h b/include/namespace.h
index ea231cacb..9dbe88aa0 100644
--- a/include/namespace.h
+++ b/include/namespace.h
@@ -7,6 +7,9 @@
# ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
# endif
+# ifndef CLONE_NEWCGROUP
+# define CLONE_NEWCGROUP 0x02000000
+# endif
# ifndef CLONE_NEWUTS
# define CLONE_NEWUTS 0x04000000
# endif
diff --git a/sys-utils/nsenter.1 b/sys-utils/nsenter.1
index 79fc2e5c6..ea5992e73 100644
--- a/sys-utils/nsenter.1
+++ b/sys-utils/nsenter.1
@@ -54,6 +54,12 @@ The process will have a distinct set of UIDs, GIDs and capabilities.
.RB ( CLONE_\:NEWUSER
flag)
.TP
+.B cgroup namespace
+The process will have a virtualized view of \fI/proc\:/self\:/cgroup\fP, and new
+cgroup mounts will be rooted at the namespace cgroup root.
+.RB ( CLONE_\:NEWCGROUP
+flag)
+.TP
See \fBclone\fP(2) for the exact semantics of the flags.
.TP
If \fIprogram\fP is not given, then ``${SHELL}'' is run (default: /bin\:/sh).
@@ -87,6 +93,9 @@ the PID namespace
/proc/\fIpid\fR/ns/user
the user namespace
.TP
+/proc/\fIpid\fR/ns/cgroup
+the cgroup namespace
+.TP
/proc/\fIpid\fR/root
the root directory
.TP
@@ -125,6 +134,11 @@ Enter the user namespace. If no file is specified, enter the user namespace of
the target process. If file is specified, enter the user namespace specified by
file. See also the \fB\-\-setuid\fR and \fB\-\-setgid\fR options.
.TP
+\fB\-C\fR, \fB\-\-cgroup\fR[=\fIfile\fR]
+Enter the cgroup namespace. If no file is specified, enter the cgroup namespace of
+the target process. If file is specified, enter the cgroup namespace specified by
+file.
+.TP
\fB\-G\fR, \fB\-\-setgid\fR \fIgid\fR
Set the group ID which will be used in the entered namespace and drop
supplementary groups.
diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c
index 371572580..d8690db36 100644
--- a/sys-utils/nsenter.c
+++ b/sys-utils/nsenter.c
@@ -52,12 +52,13 @@ static struct namespace_file {
* first. This gives an unprivileged user the potential to
* enter the other namespaces.
*/
- { .nstype = CLONE_NEWUSER, .name = "ns/user", .fd = -1 },
- { .nstype = CLONE_NEWIPC, .name = "ns/ipc", .fd = -1 },
- { .nstype = CLONE_NEWUTS, .name = "ns/uts", .fd = -1 },
- { .nstype = CLONE_NEWNET, .name = "ns/net", .fd = -1 },
- { .nstype = CLONE_NEWPID, .name = "ns/pid", .fd = -1 },
- { .nstype = CLONE_NEWNS, .name = "ns/mnt", .fd = -1 },
+ { .nstype = CLONE_NEWUSER, .name = "ns/user", .fd = -1 },
+ { .nstype = CLONE_NEWCGROUP,.name = "ns/cgroup", .fd = -1 },
+ { .nstype = CLONE_NEWIPC, .name = "ns/ipc", .fd = -1 },
+ { .nstype = CLONE_NEWUTS, .name = "ns/uts", .fd = -1 },
+ { .nstype = CLONE_NEWNET, .name = "ns/net", .fd = -1 },
+ { .nstype = CLONE_NEWPID, .name = "ns/pid", .fd = -1 },
+ { .nstype = CLONE_NEWNS, .name = "ns/mnt", .fd = -1 },
{ .nstype = 0, .name = NULL, .fd = -1 }
};
@@ -79,6 +80,7 @@ static void usage(int status)
fputs(_(" -i, --ipc[=<file>] enter System V IPC namespace\n"), out);
fputs(_(" -n, --net[=<file>] enter network namespace\n"), out);
fputs(_(" -p, --pid[=<file>] enter pid namespace\n"), out);
+ fputs(_(" -C, --cgroup[=<file>] enter cgroup namespace\n"), out);
fputs(_(" -U, --user[=<file>] enter user namespace\n"), out);
fputs(_(" -S, --setuid <uid> set uid in entered namespace\n"), out);
fputs(_(" -G, --setgid <gid> set gid in entered namespace\n"), out);
@@ -186,6 +188,7 @@ int main(int argc, char *argv[])
{ "net", optional_argument, NULL, 'n' },
{ "pid", optional_argument, NULL, 'p' },
{ "user", optional_argument, NULL, 'U' },
+ { "cgroup", optional_argument, NULL, 'C' },
{ "setuid", required_argument, NULL, 'S' },
{ "setgid", required_argument, NULL, 'G' },
{ "root", optional_argument, NULL, 'r' },
@@ -214,7 +217,7 @@ int main(int argc, char *argv[])
atexit(close_stdout);
while ((c =
- getopt_long(argc, argv, "+hVt:m::u::i::n::p::U::S:G:r::w::FZ",
+ getopt_long(argc, argv, "+hVt:m::u::i::n::p::C::U::S:G:r::w::FZ",
longopts, NULL)) != -1) {
switch (c) {
case 'h':
@@ -256,6 +259,12 @@ int main(int argc, char *argv[])
else
namespaces |= CLONE_NEWPID;
break;
+ case 'C':
+ if (optarg)
+ open_namespace_fd(CLONE_NEWCGROUP, optarg);
+ else
+ namespaces |= CLONE_NEWCGROUP;
+ break;
case 'U':
if (optarg)
open_namespace_fd(CLONE_NEWUSER, optarg);
diff --git a/sys-utils/unshare.1 b/sys-utils/unshare.1
index 264f13969..973bc048c 100644
--- a/sys-utils/unshare.1
+++ b/sys-utils/unshare.1
@@ -49,6 +49,11 @@ sockets, etc. (\fBCLONE_NEWNET\fP flag)
Children will have a distinct set of PID to process mappings from their parent.
(\fBCLONE_NEWPID\fP flag)
.TP
+.BR "cgroup namespace"
+The process will have a virtualized view of \fI/proc\:/self\:/cgroup\fP, and new
+cgroup mounts will be rooted at the namespace cgroup root.
+(\fBCLONE_NEWCGROUP\fP flag)
+.TP
.BR "user namespace"
The process will have a distinct set of UIDs, GIDs and capabilities.
(\fBCLONE_NEWUSER\fP flag)
@@ -82,6 +87,10 @@ by bind mount.
Unshare the user namespace. If \fIfile\fP is specified then persistent namespace is created
by bind mount.
.TP
+.BR \-C , " \-\-cgroup"[=\fIfile\fP]
+Unshare the cgroup namespace. If \fIfile\fP is specified then persistent namespace is created
+by bind mount.
+.TP
.BR \-f , " \-\-fork"
Fork the specified \fIprogram\fR as a child process of \fBunshare\fR rather than
running it directly. This is useful when creating a new pid namespace.
diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
index 988632062..234c7501f 100644
--- a/sys-utils/unshare.c
+++ b/sys-utils/unshare.c
@@ -53,12 +53,13 @@ static struct namespace_file {
const char *name; /* ns/<type> */
const char *target; /* user specified target for bind mount */
} namespace_files[] = {
- { .type = CLONE_NEWUSER, .name = "ns/user" },
- { .type = CLONE_NEWIPC, .name = "ns/ipc" },
- { .type = CLONE_NEWUTS, .name = "ns/uts" },
- { .type = CLONE_NEWNET, .name = "ns/net" },
- { .type = CLONE_NEWPID, .name = "ns/pid" },
- { .type = CLONE_NEWNS, .name = "ns/mnt" },
+ { .type = CLONE_NEWUSER, .name = "ns/user" },
+ { .type = CLONE_NEWCGROUP,.name = "ns/cgroup" },
+ { .type = CLONE_NEWIPC, .name = "ns/ipc" },
+ { .type = CLONE_NEWUTS, .name = "ns/uts" },
+ { .type = CLONE_NEWNET, .name = "ns/net" },
+ { .type = CLONE_NEWPID, .name = "ns/pid" },
+ { .type = CLONE_NEWNS, .name = "ns/mnt" },
{ .name = NULL }
};
@@ -255,6 +256,7 @@ static void usage(int status)
fputs(_(" -n, --net[=<file>] unshare network namespace\n"), out);
fputs(_(" -p, --pid[=<file>] unshare pid namespace\n"), out);
fputs(_(" -U, --user[=<file>] unshare user namespace\n"), out);
+ fputs(_(" -C, --cgroup[=<file>] unshare cgroup namespace\n"), out);
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);
@@ -281,12 +283,13 @@ int main(int argc, char *argv[])
{ "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' },
- { "pid", optional_argument, 0, 'p' },
- { "user", optional_argument, 0, 'U' },
+ { "mount", optional_argument, 0, 'm' },
+ { "uts", optional_argument, 0, 'u' },
+ { "ipc", optional_argument, 0, 'i' },
+ { "net", optional_argument, 0, 'n' },
+ { "pid", optional_argument, 0, 'p' },
+ { "user", optional_argument, 0, 'U' },
+ { "cgroup", optional_argument, 0, 'C' },
{ "fork", no_argument, 0, 'f' },
{ "mount-proc", optional_argument, 0, OPT_MOUNTPROC },
@@ -312,7 +315,7 @@ int main(int argc, char *argv[])
textdomain(PACKAGE);
atexit(close_stdout);
- while ((c = getopt_long(argc, argv, "+fhVmuinpUr", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "+fhVmuinpCUr", longopts, NULL)) != -1) {
switch (c) {
case 'f':
forkit = 1;
@@ -352,6 +355,11 @@ int main(int argc, char *argv[])
if (optarg)
set_ns_target(CLONE_NEWUSER, optarg);
break;
+ case 'C':
+ unshare_flags |= CLONE_NEWCGROUP;
+ if (optarg)
+ set_ns_target(CLONE_NEWCGROUP, optarg);
+ break;
case OPT_MOUNTPROC:
unshare_flags |= CLONE_NEWNS;
procmnt = optarg ? optarg : "/proc";