Implement support for cgroup namespaces
Currently these are supported in #for-next. Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
7154cc8926
commit
f9e7b66dbd
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Reference in New Issue