From 827e1a4e7dfbb985c024f362d35bd94b77dbc449 Mon Sep 17 00:00:00 2001 From: Jagger Date: Sun, 19 Jun 2016 15:50:25 +0200 Subject: [PATCH] Init cgroups from parent --- Makefile | 3 ++- cgroup.c | 50 ++++++++++++++++++++++++++++++-------------------- cgroup.h | 4 +++- cmdline.c | 13 ++----------- contain.c | 6 +++--- subproc.c | 8 +++++++- 6 files changed, 47 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index b37d808..b66a74e 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,8 @@ mount.o: mount.h common.h log.h net.o: net.h common.h log.h pid.o: pid.h common.h log.h sandbox.o: sandbox.h common.h log.h seccomp/bpf-helper.h -subproc.o: subproc.h common.h contain.h log.h net.h sandbox.h user.h util.h +subproc.o: subproc.h common.h cgroup.h contain.h log.h net.h sandbox.h user.h +subproc.o: util.h user.o: user.h common.h log.h util.h util.o: util.h common.h log.h uts.o: uts.h common.h log.h diff --git a/cgroup.c b/cgroup.c index 2d2711c..d0fc92b 100644 --- a/cgroup.c +++ b/cgroup.c @@ -21,6 +21,7 @@ #include "cgroup.h" +#include #include #include #include @@ -35,23 +36,17 @@ #include "log.h" #include "util.h" -bool cgroupInitNs(struct nsjconf_t *nsjconf) +bool cgroupInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid) { if (nsjconf->clone_newcgroup == false) { return true; } - struct timeval tv; - if (gettimeofday(&tv, NULL) == -1) { - PLOG_E("gettimeofday() failed"); - return false; - } - char mem_cgroup_path[PATH_MAX]; - snprintf(mem_cgroup_path, sizeof(mem_cgroup_path), "%s/%s/NSJAIL.%lx.%lx", - nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_parent, (unsigned long)tv.tv_sec, - (unsigned long)tv.tv_usec); - if (mkdir(mem_cgroup_path, 0700) == -1) { + snprintf(mem_cgroup_path, sizeof(mem_cgroup_path), "%s/%s/NSJAIL.%d", + nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_parent, (int)pid); + LOG_D("Create '%s' for PID=%d", mem_cgroup_path, (int)pid); + if (mkdir(mem_cgroup_path, 0700) == -1 && errno != EEXIST) { PLOG_E("mkdir('%s', 0711) failed", mem_cgroup_path); return false; } @@ -61,7 +56,7 @@ bool cgroupInitNs(struct nsjconf_t *nsjconf) char mem_max_str[512]; snprintf(mem_max_str, sizeof(mem_max_str), "%zu", nsjconf->cgroup_mem_max); snprintf(fname, sizeof(fname), "%s/memory.limit_in_bytes", mem_cgroup_path); - LOG_D("Setting %s/memory.limit_in_bytes to '%s'", mem_cgroup_path, mem_max_str); + LOG_D("Setting '%s/memory.limit_in_bytes' to '%s'", mem_cgroup_path, mem_max_str); if (utilWriteBufToFile(fname, mem_max_str, strlen(mem_max_str), O_WRONLY) == false) { LOG_E("Could not update memory cgroup max limit"); return false; @@ -69,19 +64,34 @@ bool cgroupInitNs(struct nsjconf_t *nsjconf) } char pid_str[512]; - snprintf(pid_str, sizeof(pid_str), "%ld", syscall(__NR_getpid)); + snprintf(pid_str, sizeof(pid_str), "%d", (int)pid); snprintf(fname, sizeof(fname), "%s/tasks", mem_cgroup_path); - LOG_D("Adding PID='%s' to %s/tasks", pid_str, mem_cgroup_path); + LOG_D("Adding PID='%s' to '%s/tasks'", pid_str, mem_cgroup_path); if (utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY) == false) { LOG_E("Could not update memory cgroup task list"); return false; } - LOG_D("Unmounting '%s'", nsjconf->cgroup_mem_mount); - if (umount2(nsjconf->cgroup_mem_mount, MNT_DETACH) == -1) { - PLOG_E("Could not umount2('%s', MNT_DETACH)", nsjconf->cgroup_mem_mount); - return false; - } - + return true; +} + +void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid) +{ + if (nsjconf->clone_newcgroup == false) { + return; + } + + char mem_cgroup_path[PATH_MAX]; + snprintf(mem_cgroup_path, sizeof(mem_cgroup_path), "%s/%s/NSJAIL.%d", + nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_parent, (int)pid); + LOG_D("Remove '%s'", mem_cgroup_path); + if (rmdir(mem_cgroup_path) == -1) { + PLOG_W("rmdir('%s') failed", mem_cgroup_path); + } + return; +} + +bool cgroupInitNs(void) +{ return true; } diff --git a/cgroup.h b/cgroup.h index ea224cc..0e647db 100644 --- a/cgroup.h +++ b/cgroup.h @@ -27,6 +27,8 @@ #include "common.h" -bool cgroupInitNs(struct nsjconf_t * nsjconf); +bool cgroupInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid); +bool cgroupInitNs(void); +void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid); #endif /* _CGROUP_H */ diff --git a/cmdline.c b/cmdline.c index e768b58..e9d299c 100644 --- a/cmdline.c +++ b/cmdline.c @@ -291,7 +291,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) .max_conns_per_ip = 0, .tmpfs_size = 4 * (1024 * 1024), .mount_proc = true, - .cgroup_mem_mount = "/cgroup_memory", + .cgroup_mem_mount = "/sys/fs/cgroup/memory", .cgroup_mem_parent = "NSJAIL", .cgroup_mem_max = (size_t)0, .iface_no_lo = false, @@ -376,7 +376,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) {{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"}, {{"tmpfs_size", required_argument, NULL, 0x0602}, "Number of bytes to allocate for tmpfsmounts (default: 4194304)"}, {{"disable_proc", no_argument, NULL, 0x0603}, "Disable mounting /proc in the jail"}, - {{"cgroup_mem_mount", required_argument, NULL, 0x0801}, "Where to mount memory cgroup FS (default: '/cgroup_memory'"}, + {{"cgroup_mem_mount", required_argument, NULL, 0x0801}, "Where to mount memory cgroup FS (default: '/sys/fs/cgroup/memory'"}, {{"cgroup_mem_parent", required_argument, NULL, 0x0802}, "Which memory cgroup to use as parent (default: 'NSJAIL')"}, {{"cgroup_mem_max", required_argument, NULL, 0x0803}, "Maximum number of bytes to use in the group"}, {{"iface_no_lo", no_argument, NULL, 0x700}, "Don't bring up the 'lo' interface"}, @@ -630,15 +630,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) } } - if (nsjconf->clone_newcgroup) { - struct mounts_t *p = utilMalloc(sizeof(struct mounts_t)); - p->src = NULL; - p->dst = nsjconf->cgroup_mem_mount; - p->flags = 0; - p->options = "memory"; - p->fs_type = "cgroup"; - TAILQ_INSERT_HEAD(&nsjconf->mountpts, p, pointers); - } if (nsjconf->mount_proc == true) { struct mounts_t *p = utilMalloc(sizeof(struct mounts_t)); p->src = NULL; diff --git a/contain.c b/contain.c index 6029d83..90afdea 100644 --- a/contain.c +++ b/contain.c @@ -65,9 +65,9 @@ static bool containInitUtsNs(struct nsjconf_t *nsjconf) return utsInitNs(nsjconf); } -static bool containInitCgroupNs(struct nsjconf_t *nsjconf) +static bool containInitCgroupNs(void) { - return cgroupInitNs(nsjconf); + return cgroupInitNs(); } static bool containDropPrivs(struct nsjconf_t *nsjconf) @@ -324,7 +324,7 @@ bool containContain(struct nsjconf_t * nsjconf) if (containInitUtsNs(nsjconf) == false) { return false; } - if (containInitCgroupNs(nsjconf) == false) { + if (containInitCgroupNs() == false) { return false; } if (containDropPrivs(nsjconf) == false) { diff --git a/subproc.c b/subproc.c index 1aea024..8b7b7ab 100644 --- a/subproc.c +++ b/subproc.c @@ -40,6 +40,7 @@ #include #include "common.h" +#include "cgroup.h" #include "contain.h" #include "log.h" #include "net.h" @@ -57,7 +58,7 @@ static int subprocNewProc(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int if (pipefd == -1) { if (userInitNsFromParent(nsjconf, syscall(__NR_getpid)) == false) { - LOG_E("Couldn't initialize user namespaces"); + LOG_E("Couldn't initialize net user namespace"); exit(1); } } else { @@ -227,6 +228,7 @@ int subprocReap(struct nsjconf_t *nsjconf) si.si_pid, WTERMSIG(status), subprocCount(nsjconf)); rv = 100 + WTERMSIG(status); } + cgroupFinishFromParent(nsjconf, si.si_pid); } } @@ -266,6 +268,10 @@ static bool subprocInitParent(struct nsjconf_t *nsjconf, pid_t pid, int pipefd) LOG_E("Couldn't create and put MACVTAP interface into NS of PID '%d'", pid); return false; } + if (cgroupInitNsFromParent(nsjconf, pid) == false) { + LOG_E("Couldn't initialize cgroup user namespace"); + exit(1); + } if (userInitNsFromParent(nsjconf, pid) == false) { LOG_E("Couldn't initialize user namespaces for pid %d", pid); return false;