From e3a351b335bdff431309d6cb0e5e5e356a82a647 Mon Sep 17 00:00:00 2001 From: Jagger Date: Sun, 19 Jun 2016 13:54:36 +0200 Subject: [PATCH] More memory cgroup controls --- Makefile | 2 +- cgroup.c | 36 +++++++++++++++++++++++++++++++++++- cmdline.c | 24 ++++++++++++++++++++++++ common.h | 3 +++ util.c | 2 +- 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ae54828..b37d808 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ nsjail.o: nsjail.h common.h cmdline.h log.h net.h subproc.h cmdline.o: cmdline.h common.h log.h util.h contain.o: contain.h common.h cgroup.h log.h mount.h net.h pid.h util.h uts.h log.o: log.h common.h -cgroup.o: cgroup.h common.h +cgroup.o: cgroup.h common.h log.h util.h mount.o: mount.h common.h log.h net.o: net.h common.h log.h pid.o: pid.h common.h log.h diff --git a/cgroup.c b/cgroup.c index c6323d5..4aa7f84 100644 --- a/cgroup.c +++ b/cgroup.c @@ -21,10 +21,44 @@ #include "cgroup.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "util.h" + bool cgroupInitNs(struct nsjconf_t *nsjconf) { - if (nsjconf == NULL) { + if (nsjconf->clone_newcgroup == false) { + return true; + } + + char fname[PATH_MAX]; + if (nsjconf->cgroup_mem_max != (size_t) 0) { + char mem_max_str[512]; + snprintf(mem_max_str, sizeof(mem_max_str), "%zu", nsjconf->cgroup_mem_max); + snprintf(fname, sizeof(fname), "%s/%s/memory.limit_in_bytes", + nsjconf->cgroup_mem_mount, nsjconf->cgroup_mem_group); + if (utilWriteBufToFile(fname, mem_max_str, strlen(mem_max_str), O_WRONLY) == false) { + LOG_E("Could not update memory cgroup max limit"); + return false; + } + } + + char pid_str[512]; + snprintf(pid_str, sizeof(pid_str), "%ld", syscall(__NR_getpid)); + snprintf(fname, sizeof(fname), "%s/%s/tasks", nsjconf->cgroup_mem_mount, + nsjconf->cgroup_mem_group); + if (utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY) == false) { + LOG_E("Could not update memory cgroup task list"); return false; } + return true; } diff --git a/cmdline.c b/cmdline.c index 4c5f75c..bb3f48f 100644 --- a/cmdline.c +++ b/cmdline.c @@ -291,6 +291,9 @@ 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_group = "NSJAIL", + .cgroup_mem_max = (size_t)0, .iface_no_lo = false, .iface = NULL, .iface_vs_ip = "0.0.0.0", @@ -373,6 +376,9 @@ 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_group", required_argument, NULL, 0x0802}, "Which memory cgroup to use (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"}, {{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVLAN) and put inside the subprocess' namespace as 'vs'"}, {{"iface_vs_ip", required_argument, NULL, 0x701}, "IP of the 'vs' interface"}, @@ -608,6 +614,15 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) case 0x703: nsjconf->iface_vs_gw = optarg; break; + case 0x801: + nsjconf->cgroup_mem_mount = optarg; + break; + case 0x802: + nsjconf->cgroup_mem_group = optarg; + break; + case 0x803: + nsjconf->cgroup_mem_max = (size_t) strtoull(optarg, NULL, 0); + break; default: cmdlineUsage(argv[0], custom_opts); return false; @@ -615,6 +630,15 @@ 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/common.h b/common.h index 1be6bf8..43719b5 100644 --- a/common.h +++ b/common.h @@ -130,6 +130,9 @@ struct nsjconf_t { const char *iface_vs_ip; const char *iface_vs_nm; const char *iface_vs_gw; + const char *cgroup_mem_mount; + const char *cgroup_mem_group; + size_t cgroup_mem_max; TAILQ_HEAD(envlist, charptr_t) envs; TAILQ_HEAD(pidslist, pids_t) pids; TAILQ_HEAD(mountptslist, mounts_t) mountpts; diff --git a/util.c b/util.c index be63d53..8eeeaf3 100644 --- a/util.c +++ b/util.c @@ -94,7 +94,7 @@ bool utilWriteBufToFile(char *filename, const void *buf, size_t len, int open_fl int fd; TEMP_FAILURE_RETRY(fd = open(filename, open_flags, 0644)); if (fd == -1) { - PLOG_E("Couldn't open '%s' for R/O", filename); + PLOG_E("Couldn't open '%s' for writing", filename); return false; } defer {