cgroup: move to C++
authorRobert Swiecki <robert@swiecki.net>
Fri, 9 Feb 2018 17:13:17 +0000 (18:13 +0100)
committerRobert Swiecki <robert@swiecki.net>
Fri, 9 Feb 2018 17:13:17 +0000 (18:13 +0100)
Makefile
cgroup.c [deleted file]
cgroup.cc [new file with mode: 0644]
cgroup.h
contain.cc
subproc.cc
user.cc

index b77356ba3000b0e1e4bd33f5327ef583980ee1ce..eea405e25e50efa03a1b7c522b4206914c324275 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -35,8 +35,8 @@ LDFLAGS += -pie -Wl,-z,noexecstack -lpthread $(shell pkg-config --libs protobuf)
 
 BIN = nsjail
 LIBS = kafel/libkafel.a
-SRCS_C = log.c cgroup.c mount.c user.c util.c
-SRCS_CXX = caps.cc cmdline.cc config.cc contain.cc cpu.cc net.cc nsjail.cc pid.cc sandbox.cc subproc.cc uts.cc
+SRCS_C = log.c mount.c util.c
+SRCS_CXX = caps.cc cgroup.cc cmdline.cc config.cc contain.cc cpu.cc net.cc nsjail.cc pid.cc sandbox.cc subproc.cc uts.cc user.cc
 SRCS_PROTO = config.proto
 SRCS_PB_CXX = $(SRCS_PROTO:.proto=.pb.cc)
 SRCS_PB_H = $(SRCS_PROTO:.proto=.pb.h)
@@ -98,21 +98,22 @@ indent:
 # DO NOT DELETE THIS LINE -- make depend depends on it.
 
 log.o: log.h nsjail.h
-cgroup.o: cgroup.h nsjail.h log.h util.h
 mount.o: mount.h nsjail.h common.h log.h subproc.h util.h
 util.o: util.h nsjail.h common.h log.h
 caps.o: caps.h nsjail.h common.h log.h util.h
+cgroup.o: cgroup.h nsjail.h log.h util.h
 cmdline.o: cmdline.h nsjail.h common.h log.h mount.h util.h caps.h config.h
 cmdline.o: sandbox.h user.h
 config.o: common.h config.h nsjail.h log.h mount.h util.h caps.h cmdline.h
 config.o: user.h
-contain.o: contain.h nsjail.h cgroup.h log.h mount.h caps.h cpu.h net.h pid.h
+contain.o: contain.h nsjail.h log.h mount.h caps.h cgroup.h cpu.h net.h pid.h
 contain.o: user.h uts.h
 cpu.o: cpu.h nsjail.h log.h util.h
 net.o: net.h nsjail.h log.h subproc.h
 nsjail.o: nsjail.h cmdline.h common.h log.h net.h subproc.h util.h
 pid.o: pid.h nsjail.h log.h subproc.h
 sandbox.o: sandbox.h nsjail.h kafel/include/kafel.h log.h
-subproc.o: subproc.h nsjail.h contain.h net.h sandbox.h user.h cgroup.h
+subproc.o: subproc.h nsjail.h cgroup.h contain.h net.h sandbox.h user.h
 subproc.o: common.h log.h util.h
 uts.o: uts.h nsjail.h log.h
+user.o: user.h nsjail.h common.h log.h util.h subproc.h
diff --git a/cgroup.c b/cgroup.c
deleted file mode 100644 (file)
index 8ffd25a..0000000
--- a/cgroup.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
-
-   nsjail - cgroup namespacing
-   -----------------------------------------
-
-   Copyright 2014 Google Inc. All Rights Reserved.
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-*/
-
-#include "cgroup.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "util.h"
-
-static bool cgroupInitNsFromParentMem(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (nsjconf->cgroup_mem_max == (size_t)0) {
-               return true;
-       }
-
-       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("Create '%s' for PID=%d", mem_cgroup_path, (int)pid);
-       if (mkdir(mem_cgroup_path, 0700) == -1 && errno != EEXIST) {
-               PLOG_E("mkdir('%s', 0700) failed", mem_cgroup_path);
-               return false;
-       }
-
-       char fname[PATH_MAX];
-       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' to '%s'", fname, mem_max_str);
-       if (!utilWriteBufToFile(fname, mem_max_str, strlen(mem_max_str), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update memory cgroup max limit");
-               return false;
-       }
-
-       /*
-        * Use OOM-killer instead of making processes hang/sleep
-        */
-       snprintf(fname, sizeof(fname), "%s/memory.oom_control", mem_cgroup_path);
-       LOG_D("Writting '0' '%s'", fname);
-       if (!utilWriteBufToFile(fname, "0", strlen("0"), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update memory cgroup oom control");
-               return false;
-       }
-
-       char pid_str[512];
-       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'", pid_str, fname);
-       if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update memory cgroup task list");
-               return false;
-       }
-
-       return true;
-}
-
-static bool cgroupInitNsFromParentPids(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (nsjconf->cgroup_pids_max == 0U) {
-               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', 0700) failed", pids_cgroup_path);
-               return false;
-       }
-
-       char fname[PATH_MAX];
-       char pids_max_str[512];
-       snprintf(pids_max_str, sizeof(pids_max_str), "%u", 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 | O_CLOEXEC)) {
-               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 | O_CLOEXEC)) {
-               LOG_E("Could not update pids cgroup task list");
-               return false;
-       }
-
-       return true;
-}
-
-static bool cgroupInitNsFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (nsjconf->cgroup_net_cls_classid == 0U) {
-               return true;
-       }
-
-       char net_cls_cgroup_path[PATH_MAX];
-       snprintf(net_cls_cgroup_path, sizeof(net_cls_cgroup_path), "%s/%s/NSJAIL.%d",
-           nsjconf->cgroup_net_cls_mount, nsjconf->cgroup_net_cls_parent, (int)pid);
-       LOG_D("Create '%s' for PID=%d", net_cls_cgroup_path, (int)pid);
-       if (mkdir(net_cls_cgroup_path, 0700) == -1 && errno != EEXIST) {
-               PLOG_E("mkdir('%s', 0700) failed", net_cls_cgroup_path);
-               return false;
-       }
-
-       char fname[PATH_MAX];
-       char net_cls_classid_str[512];
-       snprintf(net_cls_classid_str, sizeof(net_cls_classid_str), "0x%x",
-           nsjconf->cgroup_net_cls_classid);
-       snprintf(fname, sizeof(fname), "%s/net_cls.classid", net_cls_cgroup_path);
-       LOG_D("Setting '%s' to '%s'", fname, net_cls_classid_str);
-       if (!utilWriteBufToFile(
-               fname, net_cls_classid_str, strlen(net_cls_classid_str), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update net_cls cgroup classid");
-               return false;
-       }
-
-       char pid_str[512];
-       snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
-       snprintf(fname, sizeof(fname), "%s/tasks", net_cls_cgroup_path);
-       LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
-       if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update net_cls cgroup task list");
-               return false;
-       }
-
-       return true;
-}
-
-static bool cgroupInitNsFromParentCpu(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (nsjconf->cgroup_cpu_ms_per_sec == 0U) {
-               return true;
-       }
-
-       char cpu_cgroup_path[PATH_MAX];
-       snprintf(cpu_cgroup_path, sizeof(cpu_cgroup_path), "%s/%s/NSJAIL.%d",
-           nsjconf->cgroup_cpu_mount, nsjconf->cgroup_cpu_parent, (int)pid);
-       LOG_D("Create '%s' for PID=%d", cpu_cgroup_path, (int)pid);
-       if (mkdir(cpu_cgroup_path, 0700) == -1 && errno != EEXIST) {
-               PLOG_E("mkdir('%s', 0700) failed", cpu_cgroup_path);
-               return false;
-       }
-
-       char fname[PATH_MAX];
-       char cpu_ms_per_sec_str[512];
-       snprintf(cpu_ms_per_sec_str, sizeof(cpu_ms_per_sec_str), "%u",
-           nsjconf->cgroup_cpu_ms_per_sec * 1000U);
-       snprintf(fname, sizeof(fname), "%s/cpu.cfs_quota_us", cpu_cgroup_path);
-       LOG_D("Setting '%s' to '%s'", fname, cpu_ms_per_sec_str);
-       if (!utilWriteBufToFile(
-               fname, cpu_ms_per_sec_str, strlen(cpu_ms_per_sec_str), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update cpu quota");
-               return false;
-       }
-
-       const char cpu_period_us[] = "1000000";
-       snprintf(fname, sizeof(fname), "%s/cpu.cfs_period_us", cpu_cgroup_path);
-       LOG_D("Setting '%s' to '%s'", fname, cpu_period_us);
-       if (!utilWriteBufToFile(
-               fname, cpu_period_us, strlen(cpu_period_us), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update cpu period");
-               return false;
-       }
-
-       char pid_str[512];
-       snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
-       snprintf(fname, sizeof(fname), "%s/tasks", cpu_cgroup_path);
-       LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
-       if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
-               LOG_E("Could not update cpu cgroup task list");
-               return false;
-       }
-
-       return true;
-}
-
-bool cgroupInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (!cgroupInitNsFromParentMem(nsjconf, pid)) {
-               return false;
-       }
-       if (!cgroupInitNsFromParentPids(nsjconf, pid)) {
-               return false;
-       }
-       if (!cgroupInitNsFromParentNetCls(nsjconf, pid)) {
-               return false;
-       }
-       if (!cgroupInitNsFromParentCpu(nsjconf, pid)) {
-               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);
-       LOG_D("Remove '%s'", mem_cgroup_path);
-       if (rmdir(mem_cgroup_path) == -1) {
-               PLOG_W("rmdir('%s') failed", mem_cgroup_path);
-       }
-       return;
-}
-
-void cgroupFinishFromParentPids(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (nsjconf->cgroup_pids_max == 0U) {
-               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 cgroupFinishFromParentCpu(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (nsjconf->cgroup_cpu_ms_per_sec == 0U) {
-               return;
-       }
-       char cpu_cgroup_path[PATH_MAX];
-       snprintf(cpu_cgroup_path, sizeof(cpu_cgroup_path), "%s/%s/NSJAIL.%d",
-           nsjconf->cgroup_cpu_mount, nsjconf->cgroup_cpu_parent, (int)pid);
-       LOG_D("Remove '%s'", cpu_cgroup_path);
-       if (rmdir(cpu_cgroup_path) == -1) {
-               PLOG_W("rmdir('%s') failed", cpu_cgroup_path);
-       }
-       return;
-}
-
-void cgroupFinishFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid) {
-       if (nsjconf->cgroup_net_cls_classid == 0U) {
-               return;
-       }
-       char net_cls_cgroup_path[PATH_MAX];
-       snprintf(net_cls_cgroup_path, sizeof(net_cls_cgroup_path), "%s/%s/NSJAIL.%d",
-           nsjconf->cgroup_net_cls_mount, nsjconf->cgroup_net_cls_parent, (int)pid);
-       LOG_D("Remove '%s'", net_cls_cgroup_path);
-       if (rmdir(net_cls_cgroup_path) == -1) {
-               PLOG_W("rmdir('%s') failed", net_cls_cgroup_path);
-       }
-       return;
-}
-
-void cgroupFinishFromParent(struct nsjconf_t* nsjconf, pid_t pid) {
-       cgroupFinishFromParentMem(nsjconf, pid);
-       cgroupFinishFromParentPids(nsjconf, pid);
-       cgroupFinishFromParentNetCls(nsjconf, pid);
-       cgroupFinishFromParentCpu(nsjconf, pid);
-}
-
-bool cgroupInitNs(void) { return true; }
diff --git a/cgroup.cc b/cgroup.cc
new file mode 100644 (file)
index 0000000..618b4cc
--- /dev/null
+++ b/cgroup.cc
@@ -0,0 +1,288 @@
+/*
+
+   nsjail - cgroup namespacing
+   -----------------------------------------
+
+   Copyright 2014 Google Inc. All Rights Reserved.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+#include "cgroup.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+extern "C" {
+#include "log.h"
+#include "util.h"
+}
+
+namespace cgroup {
+
+static bool initNsFromParentMem(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (nsjconf->cgroup_mem_max == (size_t)0) {
+               return true;
+       }
+
+       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("Create '%s' for PID=%d", mem_cgroup_path, (int)pid);
+       if (mkdir(mem_cgroup_path, 0700) == -1 && errno != EEXIST) {
+               PLOG_E("mkdir('%s', 0700) failed", mem_cgroup_path);
+               return false;
+       }
+
+       char fname[PATH_MAX];
+       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' to '%s'", fname, mem_max_str);
+       if (!utilWriteBufToFile(fname, mem_max_str, strlen(mem_max_str), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update memory cgroup max limit");
+               return false;
+       }
+
+       /*
+        * Use OOM-killer instead of making processes hang/sleep
+        */
+       snprintf(fname, sizeof(fname), "%s/memory.oom_control", mem_cgroup_path);
+       LOG_D("Writting '0' '%s'", fname);
+       if (!utilWriteBufToFile(fname, "0", strlen("0"), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update memory cgroup oom control");
+               return false;
+       }
+
+       char pid_str[512];
+       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'", pid_str, fname);
+       if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update memory cgroup task list");
+               return false;
+       }
+
+       return true;
+}
+
+static bool initNsFromParentPids(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (nsjconf->cgroup_pids_max == 0U) {
+               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', 0700) failed", pids_cgroup_path);
+               return false;
+       }
+
+       char fname[PATH_MAX];
+       char pids_max_str[512];
+       snprintf(pids_max_str, sizeof(pids_max_str), "%u", 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 | O_CLOEXEC)) {
+               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 | O_CLOEXEC)) {
+               LOG_E("Could not update pids cgroup task list");
+               return false;
+       }
+
+       return true;
+}
+
+static bool initNsFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (nsjconf->cgroup_net_cls_classid == 0U) {
+               return true;
+       }
+
+       char net_cls_cgroup_path[PATH_MAX];
+       snprintf(net_cls_cgroup_path, sizeof(net_cls_cgroup_path), "%s/%s/NSJAIL.%d",
+           nsjconf->cgroup_net_cls_mount, nsjconf->cgroup_net_cls_parent, (int)pid);
+       LOG_D("Create '%s' for PID=%d", net_cls_cgroup_path, (int)pid);
+       if (mkdir(net_cls_cgroup_path, 0700) == -1 && errno != EEXIST) {
+               PLOG_E("mkdir('%s', 0700) failed", net_cls_cgroup_path);
+               return false;
+       }
+
+       char fname[PATH_MAX];
+       char net_cls_classid_str[512];
+       snprintf(net_cls_classid_str, sizeof(net_cls_classid_str), "0x%x",
+           nsjconf->cgroup_net_cls_classid);
+       snprintf(fname, sizeof(fname), "%s/net_cls.classid", net_cls_cgroup_path);
+       LOG_D("Setting '%s' to '%s'", fname, net_cls_classid_str);
+       if (!utilWriteBufToFile(
+               fname, net_cls_classid_str, strlen(net_cls_classid_str), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update net_cls cgroup classid");
+               return false;
+       }
+
+       char pid_str[512];
+       snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
+       snprintf(fname, sizeof(fname), "%s/tasks", net_cls_cgroup_path);
+       LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
+       if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update net_cls cgroup task list");
+               return false;
+       }
+
+       return true;
+}
+
+static bool initNsFromParentCpu(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (nsjconf->cgroup_cpu_ms_per_sec == 0U) {
+               return true;
+       }
+
+       char cpu_cgroup_path[PATH_MAX];
+       snprintf(cpu_cgroup_path, sizeof(cpu_cgroup_path), "%s/%s/NSJAIL.%d",
+           nsjconf->cgroup_cpu_mount, nsjconf->cgroup_cpu_parent, (int)pid);
+       LOG_D("Create '%s' for PID=%d", cpu_cgroup_path, (int)pid);
+       if (mkdir(cpu_cgroup_path, 0700) == -1 && errno != EEXIST) {
+               PLOG_E("mkdir('%s', 0700) failed", cpu_cgroup_path);
+               return false;
+       }
+
+       char fname[PATH_MAX];
+       char cpu_ms_per_sec_str[512];
+       snprintf(cpu_ms_per_sec_str, sizeof(cpu_ms_per_sec_str), "%u",
+           nsjconf->cgroup_cpu_ms_per_sec * 1000U);
+       snprintf(fname, sizeof(fname), "%s/cpu.cfs_quota_us", cpu_cgroup_path);
+       LOG_D("Setting '%s' to '%s'", fname, cpu_ms_per_sec_str);
+       if (!utilWriteBufToFile(
+               fname, cpu_ms_per_sec_str, strlen(cpu_ms_per_sec_str), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update cpu quota");
+               return false;
+       }
+
+       const char cpu_period_us[] = "1000000";
+       snprintf(fname, sizeof(fname), "%s/cpu.cfs_period_us", cpu_cgroup_path);
+       LOG_D("Setting '%s' to '%s'", fname, cpu_period_us);
+       if (!utilWriteBufToFile(
+               fname, cpu_period_us, strlen(cpu_period_us), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update cpu period");
+               return false;
+       }
+
+       char pid_str[512];
+       snprintf(pid_str, sizeof(pid_str), "%d", (int)pid);
+       snprintf(fname, sizeof(fname), "%s/tasks", cpu_cgroup_path);
+       LOG_D("Adding PID='%s' to '%s'", pid_str, fname);
+       if (!utilWriteBufToFile(fname, pid_str, strlen(pid_str), O_WRONLY | O_CLOEXEC)) {
+               LOG_E("Could not update cpu cgroup task list");
+               return false;
+       }
+
+       return true;
+}
+
+bool initNsFromParent(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (!initNsFromParentMem(nsjconf, pid)) {
+               return false;
+       }
+       if (!initNsFromParentPids(nsjconf, pid)) {
+               return false;
+       }
+       if (!initNsFromParentNetCls(nsjconf, pid)) {
+               return false;
+       }
+       if (!initNsFromParentCpu(nsjconf, pid)) {
+               return false;
+       }
+       return true;
+}
+
+void finishFromParentMem(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);
+       LOG_D("Remove '%s'", mem_cgroup_path);
+       if (rmdir(mem_cgroup_path) == -1) {
+               PLOG_W("rmdir('%s') failed", mem_cgroup_path);
+       }
+       return;
+}
+
+void finishFromParentPids(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (nsjconf->cgroup_pids_max == 0U) {
+               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 finishFromParentCpu(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (nsjconf->cgroup_cpu_ms_per_sec == 0U) {
+               return;
+       }
+       char cpu_cgroup_path[PATH_MAX];
+       snprintf(cpu_cgroup_path, sizeof(cpu_cgroup_path), "%s/%s/NSJAIL.%d",
+           nsjconf->cgroup_cpu_mount, nsjconf->cgroup_cpu_parent, (int)pid);
+       LOG_D("Remove '%s'", cpu_cgroup_path);
+       if (rmdir(cpu_cgroup_path) == -1) {
+               PLOG_W("rmdir('%s') failed", cpu_cgroup_path);
+       }
+       return;
+}
+
+void finishFromParentNetCls(struct nsjconf_t* nsjconf, pid_t pid) {
+       if (nsjconf->cgroup_net_cls_classid == 0U) {
+               return;
+       }
+       char net_cls_cgroup_path[PATH_MAX];
+       snprintf(net_cls_cgroup_path, sizeof(net_cls_cgroup_path), "%s/%s/NSJAIL.%d",
+           nsjconf->cgroup_net_cls_mount, nsjconf->cgroup_net_cls_parent, (int)pid);
+       LOG_D("Remove '%s'", net_cls_cgroup_path);
+       if (rmdir(net_cls_cgroup_path) == -1) {
+               PLOG_W("rmdir('%s') failed", net_cls_cgroup_path);
+       }
+       return;
+}
+
+void finishFromParent(struct nsjconf_t* nsjconf, pid_t pid) {
+       finishFromParentMem(nsjconf, pid);
+       finishFromParentPids(nsjconf, pid);
+       finishFromParentNetCls(nsjconf, pid);
+       finishFromParentCpu(nsjconf, pid);
+}
+
+bool initNs(void) { return true; }
+
+}  // namespace cgroup
index c34cd247f834bc1612849de03221933083befb37..677ce36969813e32a94f8f16ff35ef84df5d720a 100644 (file)
--- a/cgroup.h
+++ b/cgroup.h
 
 #include "nsjail.h"
 
-bool cgroupInitNsFromParent(struct nsjconf_t* nsjconf, pid_t pid);
-bool cgroupInitNs(void);
-void cgroupFinishFromParent(struct nsjconf_t* nsjconf, pid_t pid);
+namespace cgroup {
+
+bool initNsFromParent(struct nsjconf_t* nsjconf, pid_t pid);
+bool initNs(void);
+void finishFromParent(struct nsjconf_t* nsjconf, pid_t pid);
+
+}  // namespace cgroup
 
 #endif /* _CGROUP_H */
index 61f47e7bf242188d44ee721c8ea0a1ead13cf489..42a0bdada3611104c54a7b2e11a9e2a80432f851 100644 (file)
 #include <unistd.h>
 
 extern "C" {
-#include "cgroup.h"
 #include "log.h"
 #include "mount.h"
 }
 
 #include "caps.h"
+#include "cgroup.h"
 #include "cpu.h"
 #include "net.h"
 #include "pid.h"
@@ -60,7 +60,7 @@ static bool containInitNetNs(struct nsjconf_t* nsjconf) { return net::initNsFrom
 
 static bool containInitUtsNs(struct nsjconf_t* nsjconf) { return uts::initNs(nsjconf); }
 
-static bool containInitCgroupNs(void) { return cgroupInitNs(); }
+static bool containInitCgroupNs(void) { return cgroup::initNs(); }
 
 static bool containDropPrivs(struct nsjconf_t* nsjconf) {
 #ifndef PR_SET_NO_NEW_PRIVS
index 7e91bf3fed5a5b6ddb166a0071c9c0d8089578e0..6cce1b6a953a6d65ce9dad0a6b206adddd11d5f5 100644 (file)
 #include <time.h>
 #include <unistd.h>
 
+#include "cgroup.h"
 #include "contain.h"
 #include "net.h"
 #include "sandbox.h"
 #include "user.h"
 
 extern "C" {
-#include "cgroup.h"
 #include "common.h"
 #include "log.h"
 #include "util.h"
@@ -148,7 +148,7 @@ static int subprocNewProc(
                        LOG_E("Couldn't initialize net user namespace");
                        _exit(0xff);
                }
-               if (cgroupInitNsFromParent(nsjconf, getpid()) == false) {
+               if (cgroup::initNsFromParent(nsjconf, getpid()) == false) {
                        LOG_E("Couldn't initialize net user namespace");
                        _exit(0xff);
                }
@@ -317,7 +317,7 @@ int reapProc(struct nsjconf_t* nsjconf) {
                }
 
                if (wait4(si.si_pid, &status, WNOHANG, NULL) == si.si_pid) {
-                       cgroupFinishFromParent(nsjconf, si.si_pid);
+                       cgroup::finishFromParent(nsjconf, si.si_pid);
 
                        const char* remote_txt = "[UNKNOWN]";
                        struct pids_t* elem = getPidElem(nsjconf, si.si_pid);
@@ -380,7 +380,7 @@ static bool initParent(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) {
+       if (cgroup::initNsFromParent(nsjconf, pid) == false) {
                LOG_E("Couldn't initialize cgroup user namespace");
                exit(0xff);
        }
diff --git a/user.cc b/user.cc
index d10f2aff9d8e80ebd197bb3cfe5b9785db63752a..a4a44a731d78c947c38e22371e2aa5b1fd62046e 100644 (file)
--- a/user.cc
+++ b/user.cc
@@ -349,8 +349,8 @@ static gid_t parseGid(const char* id) {
        return (gid_t)-1;
 }
 
-bool parseId(struct nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt,
-    bool is_gid, bool is_newidmap) {
+bool parseId(struct nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt, bool is_gid,
+    bool is_newidmap) {
        uid_t inside_id;
        uid_t outside_id;