]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
Implement support for cgroup namespaces
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Thu, 3 Mar 2016 01:53:42 +0000 (17:53 -0800)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Thu, 3 Mar 2016 01:53:42 +0000 (17:53 -0800)
Currently these are supported in #for-next.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
include/namespace.h
sys-utils/nsenter.1
sys-utils/nsenter.c
sys-utils/unshare.1
sys-utils/unshare.c

index ea231cacbae29820f29ac9362d5d60622a5373d3..9dbe88aa07f82fc559424fa09c0368ebfb91f56e 100644 (file)
@@ -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
index 79fc2e5c6fd3dbbdec41ecfcfa9b05129c965579..ea5992e7391d30541440f51de4b1ae4ccb7af3e4 100644 (file)
@@ -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.
index 37157258019331703fdc8f34325fda45102d33db..d8690db367ea018c1e8a26201cd6c5cb792106b8 100644 (file)
@@ -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);
index 264f1396980994e394a44be5ca6d00aaf54a26e5..973bc048c99006bd10717aeff0e0323c92faa44f 100644 (file)
@@ -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.
index 988632062c00952f271bebd7a2760d7fb11ecd3e..234c7501fa8ac59f955468f25b113708b9cf5e2b 100644 (file)
@@ -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";