From cc5d4b65c9234a91e0acc6d91f3908e8e4c65b1d Mon Sep 17 00:00:00 2001 From: Robert Swiecki Date: Thu, 20 Apr 2017 17:48:20 +0200 Subject: [PATCH] cgroups: support for PIDs --- cgroup.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- cmdline.c | 15 +++++++++++ common.h | 3 +++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/cgroup.c b/cgroup.c index 405c327..aeee42d 100644 --- a/cgroup.c +++ b/cgroup.c @@ -36,7 +36,7 @@ #include "log.h" #include "util.h" -bool cgroupInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid) +static bool cgroupInitNsFromParentMem(struct nsjconf_t *nsjconf, pid_t pid) { if (nsjconf->cgroup_mem_max == (size_t) 0) { return true; @@ -85,12 +85,62 @@ bool cgroupInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid) return true; } -void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid) +static bool cgroupInitNsFromParentPids(struct nsjconf_t *nsjconf, pid_t pid) +{ + if (nsjconf->cgroup_pids_max == (size_t) 0) { + return true; + } + + char pids_cgroup_path[PATH_MAX]; + snprintf(pids_cgroup_path, sizeof(pids_cgroup_path), "%s/%s/NSJAIL.%d", + nsjconf->cgroup_pids_mount, nsjconf->cgroup_pids_parent, (int)pid); + LOG_D("Create '%s' for PID=%d", pids_cgroup_path, (int)pid); + if (mkdir(pids_cgroup_path, 0700) == -1 && errno != EEXIST) { + PLOG_E("mkdir('%s', 0711) failed", pids_cgroup_path); + return false; + } + + char fname[PATH_MAX]; + if (nsjconf->cgroup_pids_max != (size_t) 0) { + char pids_max_str[512]; + snprintf(pids_max_str, sizeof(pids_max_str), "%zu", nsjconf->cgroup_pids_max); + snprintf(fname, sizeof(fname), "%s/pids.max", pids_cgroup_path); + LOG_D("Setting '%s' to '%s'", fname, pids_max_str); + if (utilWriteBufToFile(fname, pids_max_str, strlen(pids_max_str), O_WRONLY) == + false) { + LOG_E("Could not update pids cgroup max limit"); + return false; + } + } + + char pid_str[512]; + snprintf(pid_str, sizeof(pid_str), "%d", (int)pid); + snprintf(fname, sizeof(fname), "%s/tasks", pids_cgroup_path); + LOG_D("Adding PID='%s' to '%s'", pid_str, fname); + if (utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY) == false) { + LOG_E("Could not update pids cgroup task list"); + return false; + } + + return true; +} + +bool cgroupInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid) +{ + if (cgroupInitNsFromParentMem(nsjconf, pid) == false) { + return false; + } + if (cgroupInitNsFromParentPids(nsjconf, pid) == false) { + return false; + } + return true; +} + +void cgroupFinishFromParentMem(struct nsjconf_t *nsjconf, pid_t pid) { if (nsjconf->cgroup_mem_max == (size_t) 0) { 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); @@ -101,6 +151,27 @@ void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid) return; } +void cgroupFinishFromParentPids(struct nsjconf_t *nsjconf, pid_t pid) +{ + if (nsjconf->cgroup_pids_max == (size_t) 0) { + return; + } + char pids_cgroup_path[PATH_MAX]; + snprintf(pids_cgroup_path, sizeof(pids_cgroup_path), "%s/%s/NSJAIL.%d", + nsjconf->cgroup_pids_mount, nsjconf->cgroup_pids_parent, (int)pid); + LOG_D("Remove '%s'", pids_cgroup_path); + if (rmdir(pids_cgroup_path) == -1) { + PLOG_W("rmdir('%s') failed", pids_cgroup_path); + } + return; +} + +void cgroupFinishFromParent(struct nsjconf_t *nsjconf, pid_t pid) +{ + cgroupFinishFromParentMem(nsjconf, pid); + cgroupFinishFromParentPids(nsjconf, pid); +} + bool cgroupInitNs(void) { return true; diff --git a/cmdline.c b/cmdline.c index 5ccfa2a..93384eb 100644 --- a/cmdline.c +++ b/cmdline.c @@ -324,6 +324,9 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) .cgroup_mem_mount = "/sys/fs/cgroup/memory", .cgroup_mem_parent = "NSJAIL", .cgroup_mem_max = (size_t)0, + .cgroup_pids_mount = "/sys/fs/cgroup/pids", + .cgroup_pids_parent = "NSJAIL", + .cgroup_pids_max = (size_t)0, .iface_no_lo = false, .iface = NULL, .iface_vs_ip = "0.0.0.0", @@ -419,6 +422,9 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) {{"cgroup_mem_max", required_argument, NULL, 0x0801}, "Maximum number of bytes to use in the group (default: '0' - disabled)"}, {{"cgroup_mem_mount", required_argument, NULL, 0x0802}, "Location of memory cgroup FS (default: '/sys/fs/cgroup/memory')"}, {{"cgroup_mem_parent", required_argument, NULL, 0x0803}, "Which pre-existing memory cgroup to use as a parent (default: 'NSJAIL')"}, + {{"cgroup_pids_max", required_argument, NULL, 0x0811}, "Maximum number of pids in a cgroup (default: '0' - disabled)"}, + {{"cgroup_pids_mount", required_argument, NULL, 0x0812}, "Location of pids cgroup FS (default: '/sys/fs/cgroup/pids')"}, + {{"cgroup_pids_parent", required_argument, NULL, 0x0813}, "Which pre-existing pids cgroup to use as a parent (default: 'NSJAIL')"}, {{"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"}, @@ -686,6 +692,15 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf) case 0x803: nsjconf->cgroup_mem_parent = optarg; break; + case 0x811: + nsjconf->cgroup_pids_max = (size_t) strtoull(optarg, NULL, 0); + break; + case 0x812: + nsjconf->cgroup_pids_mount = optarg; + break; + case 0x813: + nsjconf->cgroup_pids_parent = optarg; + break; case 'P': if ((nsjconf->kafel_file = fopen(optarg, "r")) == NULL) { PLOG_F("Couldn't open '%s'", optarg); diff --git a/common.h b/common.h index 5d5e027..37d241a 100644 --- a/common.h +++ b/common.h @@ -146,6 +146,9 @@ struct nsjconf_t { const char *cgroup_mem_mount; const char *cgroup_mem_parent; size_t cgroup_mem_max; + const char *cgroup_pids_mount; + const char *cgroup_pids_parent; + size_t cgroup_pids_max; FILE *kafel_file; char *kafel_string; TAILQ_HEAD(uidlist, idmap_t) uids;