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
|
# ifndef CLONE_NEWNS
|
||||||
# define CLONE_NEWNS 0x00020000
|
# define CLONE_NEWNS 0x00020000
|
||||||
# endif
|
# endif
|
||||||
|
# ifndef CLONE_NEWCGROUP
|
||||||
|
# define CLONE_NEWCGROUP 0x02000000
|
||||||
|
# endif
|
||||||
# ifndef CLONE_NEWUTS
|
# ifndef CLONE_NEWUTS
|
||||||
# define CLONE_NEWUTS 0x04000000
|
# define CLONE_NEWUTS 0x04000000
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -54,6 +54,12 @@ The process will have a distinct set of UIDs, GIDs and capabilities.
|
||||||
.RB ( CLONE_\:NEWUSER
|
.RB ( CLONE_\:NEWUSER
|
||||||
flag)
|
flag)
|
||||||
.TP
|
.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.
|
See \fBclone\fP(2) for the exact semantics of the flags.
|
||||||
.TP
|
.TP
|
||||||
If \fIprogram\fP is not given, then ``${SHELL}'' is run (default: /bin\:/sh).
|
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
|
/proc/\fIpid\fR/ns/user
|
||||||
the user namespace
|
the user namespace
|
||||||
.TP
|
.TP
|
||||||
|
/proc/\fIpid\fR/ns/cgroup
|
||||||
|
the cgroup namespace
|
||||||
|
.TP
|
||||||
/proc/\fIpid\fR/root
|
/proc/\fIpid\fR/root
|
||||||
the root directory
|
the root directory
|
||||||
.TP
|
.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
|
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.
|
file. See also the \fB\-\-setuid\fR and \fB\-\-setgid\fR options.
|
||||||
.TP
|
.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
|
\fB\-G\fR, \fB\-\-setgid\fR \fIgid\fR
|
||||||
Set the group ID which will be used in the entered namespace and drop
|
Set the group ID which will be used in the entered namespace and drop
|
||||||
supplementary groups.
|
supplementary groups.
|
||||||
|
|
|
@ -53,6 +53,7 @@ static struct namespace_file {
|
||||||
* enter the other namespaces.
|
* enter the other namespaces.
|
||||||
*/
|
*/
|
||||||
{ .nstype = CLONE_NEWUSER, .name = "ns/user", .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_NEWIPC, .name = "ns/ipc", .fd = -1 },
|
||||||
{ .nstype = CLONE_NEWUTS, .name = "ns/uts", .fd = -1 },
|
{ .nstype = CLONE_NEWUTS, .name = "ns/uts", .fd = -1 },
|
||||||
{ .nstype = CLONE_NEWNET, .name = "ns/net", .fd = -1 },
|
{ .nstype = CLONE_NEWNET, .name = "ns/net", .fd = -1 },
|
||||||
|
@ -79,6 +80,7 @@ static void usage(int status)
|
||||||
fputs(_(" -i, --ipc[=<file>] enter System V IPC namespace\n"), out);
|
fputs(_(" -i, --ipc[=<file>] enter System V IPC namespace\n"), out);
|
||||||
fputs(_(" -n, --net[=<file>] enter network namespace\n"), out);
|
fputs(_(" -n, --net[=<file>] enter network namespace\n"), out);
|
||||||
fputs(_(" -p, --pid[=<file>] enter pid 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(_(" -U, --user[=<file>] enter user namespace\n"), out);
|
||||||
fputs(_(" -S, --setuid <uid> set uid in entered 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);
|
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' },
|
{ "net", optional_argument, NULL, 'n' },
|
||||||
{ "pid", optional_argument, NULL, 'p' },
|
{ "pid", optional_argument, NULL, 'p' },
|
||||||
{ "user", optional_argument, NULL, 'U' },
|
{ "user", optional_argument, NULL, 'U' },
|
||||||
|
{ "cgroup", optional_argument, NULL, 'C' },
|
||||||
{ "setuid", required_argument, NULL, 'S' },
|
{ "setuid", required_argument, NULL, 'S' },
|
||||||
{ "setgid", required_argument, NULL, 'G' },
|
{ "setgid", required_argument, NULL, 'G' },
|
||||||
{ "root", optional_argument, NULL, 'r' },
|
{ "root", optional_argument, NULL, 'r' },
|
||||||
|
@ -214,7 +217,7 @@ int main(int argc, char *argv[])
|
||||||
atexit(close_stdout);
|
atexit(close_stdout);
|
||||||
|
|
||||||
while ((c =
|
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) {
|
longopts, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
|
@ -256,6 +259,12 @@ int main(int argc, char *argv[])
|
||||||
else
|
else
|
||||||
namespaces |= CLONE_NEWPID;
|
namespaces |= CLONE_NEWPID;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
if (optarg)
|
||||||
|
open_namespace_fd(CLONE_NEWCGROUP, optarg);
|
||||||
|
else
|
||||||
|
namespaces |= CLONE_NEWCGROUP;
|
||||||
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
open_namespace_fd(CLONE_NEWUSER, 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.
|
Children will have a distinct set of PID to process mappings from their parent.
|
||||||
(\fBCLONE_NEWPID\fP flag)
|
(\fBCLONE_NEWPID\fP flag)
|
||||||
.TP
|
.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"
|
.BR "user namespace"
|
||||||
The process will have a distinct set of UIDs, GIDs and capabilities.
|
The process will have a distinct set of UIDs, GIDs and capabilities.
|
||||||
(\fBCLONE_NEWUSER\fP flag)
|
(\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
|
Unshare the user namespace. If \fIfile\fP is specified then persistent namespace is created
|
||||||
by bind mount.
|
by bind mount.
|
||||||
.TP
|
.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"
|
.BR \-f , " \-\-fork"
|
||||||
Fork the specified \fIprogram\fR as a child process of \fBunshare\fR rather than
|
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.
|
running it directly. This is useful when creating a new pid namespace.
|
||||||
|
|
|
@ -54,6 +54,7 @@ static struct namespace_file {
|
||||||
const char *target; /* user specified target for bind mount */
|
const char *target; /* user specified target for bind mount */
|
||||||
} namespace_files[] = {
|
} namespace_files[] = {
|
||||||
{ .type = CLONE_NEWUSER, .name = "ns/user" },
|
{ .type = CLONE_NEWUSER, .name = "ns/user" },
|
||||||
|
{ .type = CLONE_NEWCGROUP,.name = "ns/cgroup" },
|
||||||
{ .type = CLONE_NEWIPC, .name = "ns/ipc" },
|
{ .type = CLONE_NEWIPC, .name = "ns/ipc" },
|
||||||
{ .type = CLONE_NEWUTS, .name = "ns/uts" },
|
{ .type = CLONE_NEWUTS, .name = "ns/uts" },
|
||||||
{ .type = CLONE_NEWNET, .name = "ns/net" },
|
{ .type = CLONE_NEWNET, .name = "ns/net" },
|
||||||
|
@ -255,6 +256,7 @@ static void usage(int status)
|
||||||
fputs(_(" -n, --net[=<file>] unshare network namespace\n"), out);
|
fputs(_(" -n, --net[=<file>] unshare network namespace\n"), out);
|
||||||
fputs(_(" -p, --pid[=<file>] unshare pid namespace\n"), out);
|
fputs(_(" -p, --pid[=<file>] unshare pid namespace\n"), out);
|
||||||
fputs(_(" -U, --user[=<file>] unshare user 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(_(" -f, --fork fork before launching <program>\n"), out);
|
||||||
fputs(_(" --mount-proc[=<dir>] mount proc filesystem first (implies --mount)\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(_(" -r, --map-root-user map current user to root (implies --user)\n"), out);
|
||||||
|
@ -287,6 +289,7 @@ int main(int argc, char *argv[])
|
||||||
{ "net", optional_argument, 0, 'n' },
|
{ "net", optional_argument, 0, 'n' },
|
||||||
{ "pid", optional_argument, 0, 'p' },
|
{ "pid", optional_argument, 0, 'p' },
|
||||||
{ "user", optional_argument, 0, 'U' },
|
{ "user", optional_argument, 0, 'U' },
|
||||||
|
{ "cgroup", optional_argument, 0, 'C' },
|
||||||
|
|
||||||
{ "fork", no_argument, 0, 'f' },
|
{ "fork", no_argument, 0, 'f' },
|
||||||
{ "mount-proc", optional_argument, 0, OPT_MOUNTPROC },
|
{ "mount-proc", optional_argument, 0, OPT_MOUNTPROC },
|
||||||
|
@ -312,7 +315,7 @@ int main(int argc, char *argv[])
|
||||||
textdomain(PACKAGE);
|
textdomain(PACKAGE);
|
||||||
atexit(close_stdout);
|
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) {
|
switch (c) {
|
||||||
case 'f':
|
case 'f':
|
||||||
forkit = 1;
|
forkit = 1;
|
||||||
|
@ -352,6 +355,11 @@ int main(int argc, char *argv[])
|
||||||
if (optarg)
|
if (optarg)
|
||||||
set_ns_target(CLONE_NEWUSER, optarg);
|
set_ns_target(CLONE_NEWUSER, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
unshare_flags |= CLONE_NEWCGROUP;
|
||||||
|
if (optarg)
|
||||||
|
set_ns_target(CLONE_NEWCGROUP, optarg);
|
||||||
|
break;
|
||||||
case OPT_MOUNTPROC:
|
case OPT_MOUNTPROC:
|
||||||
unshare_flags |= CLONE_NEWNS;
|
unshare_flags |= CLONE_NEWNS;
|
||||||
procmnt = optarg ? optarg : "/proc";
|
procmnt = optarg ? optarg : "/proc";
|
||||||
|
|
Loading…
Reference in New Issue