From 29a556068a7491c0c4cf59783a298e317d1f3e09 Mon Sep 17 00:00:00 2001 From: Johan Kartiwa Date: Wed, 15 Sep 2021 16:37:10 -0700 Subject: [PATCH] Add support for setting cgroup memory.memsw.limit_in_bytes --- README.md | 2 ++ cgroup.cc | 18 +++++++++++++----- cmdline.cc | 5 +++++ config.cc | 1 + config.proto | 2 ++ nsjail.1 | 3 +++ nsjail.h | 1 + 7 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6b2f5eb..89a5e73 100644 --- a/README.md +++ b/README.md @@ -472,6 +472,8 @@ Options: Use SECCOMP_FILTER_FLAG_LOG. Log all actions except SECCOMP_RET_ALLOW). Supported since kernel version 4.14 --cgroup_mem_max VALUE Maximum number of bytes to use in the group (default: '0' - disabled) + --cgroup_mem_memsw_max VALUE + Maximum number of memory+Swap bytes to use in the group (default: '0' - disabled) --cgroup_mem_mount VALUE Location of memory cgroup FS (default: '/sys/fs/cgroup/memory') --cgroup_mem_parent VALUE diff --git a/cgroup.cc b/cgroup.cc index 15c7649..3df35c1 100644 --- a/cgroup.cc +++ b/cgroup.cc @@ -65,7 +65,7 @@ static bool addPidToTaskList(const std::string& cgroup_path, pid_t pid) { } static bool initNsFromParentMem(nsjconf_t* nsjconf, pid_t pid) { - if (nsjconf->cgroup_mem_max == (size_t)0) { + if (nsjconf->cgroup_mem_max == (size_t)0 && nsjconf->cgroup_mem_memsw_max == (size_t)0) { return true; } @@ -73,16 +73,24 @@ static bool initNsFromParentMem(nsjconf_t* nsjconf, pid_t pid) { "/NSJAIL." + std::to_string(pid); RETURN_ON_FAILURE(createCgroup(mem_cgroup_path, pid)); - std::string mem_max_str = std::to_string(nsjconf->cgroup_mem_max); - RETURN_ON_FAILURE(writeToCgroup( - mem_cgroup_path + "/memory.limit_in_bytes", mem_max_str, "memory cgroup max limit")); - /* * Use OOM-killer instead of making processes hang/sleep */ RETURN_ON_FAILURE(writeToCgroup( mem_cgroup_path + "/memory.oom_control", "0", "memory cgroup oom control")); + if (nsjconf->cgroup_mem_max > (size_t)0) { + std::string mem_max_str = std::to_string(nsjconf->cgroup_mem_max); + RETURN_ON_FAILURE(writeToCgroup( + mem_cgroup_path + "/memory.limit_in_bytes", mem_max_str, "memory cgroup max limit")); + } + + if (nsjconf->cgroup_mem_memsw_max > (size_t)0) { + std::string mem_memsw_max_str = std::to_string(nsjconf->cgroup_mem_memsw_max); + RETURN_ON_FAILURE(writeToCgroup( + mem_cgroup_path + "/memory.memsw.limit_in_bytes", mem_memsw_max_str, "memory+Swap cgroup max limit")); + } + return addPidToTaskList(mem_cgroup_path, pid); } diff --git a/cmdline.cc b/cmdline.cc index 9aa1aba..d51a1ec 100644 --- a/cmdline.cc +++ b/cmdline.cc @@ -143,6 +143,7 @@ struct custom_option custom_opts[] = { { { "seccomp_log", no_argument, NULL, 0x0902 }, "Use SECCOMP_FILTER_FLAG_LOG. Log all actions except SECCOMP_RET_ALLOW). Supported since kernel version 4.14" }, { { "nice_level", required_argument, NULL, 0x0903 }, "Set jailed process niceness (-20 is highest -priority, 19 is lowest). By default, set to 19" }, { { "cgroup_mem_max", required_argument, NULL, 0x0801 }, "Maximum number of bytes to use in the group (default: '0' - disabled)" }, + { { "cgroup_mem_memsw_max", required_argument, NULL, 0x0804 }, "Maximum number of memory+Swap 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)" }, @@ -457,6 +458,7 @@ std::unique_ptr parseArgs(int argc, char* argv[]) { nsjconf->cgroup_mem_mount = "/sys/fs/cgroup/memory"; nsjconf->cgroup_mem_parent = "NSJAIL"; nsjconf->cgroup_mem_max = (size_t)0; + nsjconf->cgroup_mem_memsw_max = (size_t)0; nsjconf->cgroup_pids_mount = "/sys/fs/cgroup/pids"; nsjconf->cgroup_pids_parent = "NSJAIL"; nsjconf->cgroup_pids_max = 0U; @@ -861,6 +863,9 @@ std::unique_ptr parseArgs(int argc, char* argv[]) { case 0x803: nsjconf->cgroup_mem_parent = optarg; break; + case 0x804: + nsjconf->cgroup_mem_memsw_max = (size_t)strtoull(optarg, NULL, 0); + break; case 0x811: nsjconf->cgroup_pids_max = (unsigned int)strtoul(optarg, NULL, 0); break; diff --git a/config.cc b/config.cc index 551e59d..d42d9e1 100644 --- a/config.cc +++ b/config.cc @@ -251,6 +251,7 @@ static bool configParseInternal(nsjconf_t* nsjconf, const nsjail::NsJailConfig& nsjconf->nice_level = njc.nice_level(); nsjconf->cgroup_mem_max = njc.cgroup_mem_max(); + nsjconf->cgroup_mem_memsw_max = njc.cgroup_mem_memsw_max(); nsjconf->cgroup_mem_mount = njc.cgroup_mem_mount(); nsjconf->cgroup_mem_parent = njc.cgroup_mem_parent(); nsjconf->cgroup_pids_max = njc.cgroup_pids_max(); diff --git a/config.proto b/config.proto index 96a2b10..49b0489 100644 --- a/config.proto +++ b/config.proto @@ -211,6 +211,8 @@ message NsJailConfig { /* If > 0, maximum cumulative size of RAM used inside any jail */ optional uint64 cgroup_mem_max = 67 [default = 0]; /* In bytes */ + /* If > 0, maximum cumulative size of RAM + swap used inside any jail */ + optional uint64 cgroup_mem_memsw_max = 91 [default = 0]; /* In bytes */ /* Mount point for cgroups-memory in your system */ optional string cgroup_mem_mount = 68 [default = "/sys/fs/cgroup/memory"]; /* Writeable directory (for the nsjail user) under cgroup_mem_mount */ diff --git a/nsjail.1 b/nsjail.1 index f82042a..1222f31 100644 --- a/nsjail.1 +++ b/nsjail.1 @@ -220,6 +220,9 @@ Use SECCOMP_FILTER_FLAG_LOG. Log all actions except SECCOMP_RET_ALLOW. Supported \fB\-\-cgroup_mem_max\fR VALUE Maximum number of bytes to use in the group (default: '0' \- disabled) .TP +\fB\-\-cgroup_mem_memsw_max\fR VALUE +Maximum number of memory+Swap bytes to use in the group (default: '0' \- disabled) +.TP \fB\-\-cgroup_mem_mount\fR VALUE Location of memory cgroup FS (default: '/sys/fs/cgroup/memory') .TP diff --git a/nsjail.h b/nsjail.h index fc8bf70..98c66c5 100644 --- a/nsjail.h +++ b/nsjail.h @@ -148,6 +148,7 @@ struct nsjconf_t { std::string cgroup_mem_mount; std::string cgroup_mem_parent; size_t cgroup_mem_max; + size_t cgroup_mem_memsw_max; std::string cgroup_pids_mount; std::string cgroup_pids_parent; unsigned int cgroup_pids_max;