From: Serge Hallyn Date: Thu, 3 Mar 2016 01:53:42 +0000 (-0800) Subject: Implement support for cgroup namespaces X-Git-Tag: v2.28-rc2~14^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9e7b66dbded19d798b883be68b0613749d7b8bb;p=thirdparty%2Futil-linux.git Implement support for cgroup namespaces Currently these are supported in #for-next. Signed-off-by: Serge Hallyn --- diff --git a/include/namespace.h b/include/namespace.h index ea231cacba..9dbe88aa07 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 79fc2e5c6f..ea5992e739 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 3715725801..d8690db367 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[=] enter System V IPC namespace\n"), out); fputs(_(" -n, --net[=] enter network namespace\n"), out); fputs(_(" -p, --pid[=] enter pid namespace\n"), out); + fputs(_(" -C, --cgroup[=] enter cgroup namespace\n"), out); fputs(_(" -U, --user[=] enter user namespace\n"), out); fputs(_(" -S, --setuid set uid in entered namespace\n"), out); fputs(_(" -G, --setgid 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 264f139698..973bc048c9 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 988632062c..234c7501fa 100644 --- a/sys-utils/unshare.c +++ b/sys-utils/unshare.c @@ -53,12 +53,13 @@ static struct namespace_file { const char *name; /* ns/ */ 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[=] unshare network namespace\n"), out); fputs(_(" -p, --pid[=] unshare pid namespace\n"), out); fputs(_(" -U, --user[=] unshare user namespace\n"), out); + fputs(_(" -C, --cgroup[=] unshare cgroup namespace\n"), out); fputs(_(" -f, --fork fork before launching \n"), out); fputs(_(" --mount-proc[=] 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";