diff --git a/README.md b/README.md index 89a5e73..46fe950 100644 --- a/README.md +++ b/README.md @@ -474,6 +474,8 @@ Options: 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_swap_max VALUE + Maximum number of swap bytes to use in the group (default: '-1' - 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 a984122..c5ce485 100644 --- a/cgroup.cc +++ b/cgroup.cc @@ -65,7 +65,12 @@ 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 && nsjconf->cgroup_mem_memsw_max == (size_t)0) { + size_t memsw_max = nsjconf->cgroup_mem_memsw_max; + if (nsjconf->cgroup_mem_swap_max >= (ssize_t)0) { + memsw_max = nsjconf->cgroup_mem_swap_max + nsjconf->cgroup_mem_max; + } + + if (nsjconf->cgroup_mem_max == (size_t)0 && memsw_max == (size_t)0) { return true; } @@ -85,8 +90,8 @@ static bool initNsFromParentMem(nsjconf_t* nsjconf, pid_t pid) { 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); + if (memsw_max > (size_t)0) { + std::string mem_memsw_max_str = std::to_string(memsw_max); RETURN_ON_FAILURE(writeToCgroup(mem_cgroup_path + "/memory.memsw.limit_in_bytes", mem_memsw_max_str, "memory+Swap cgroup max limit")); } diff --git a/cgroup2.cc b/cgroup2.cc index 0f90551..1902c5e 100644 --- a/cgroup2.cc +++ b/cgroup2.cc @@ -84,7 +84,12 @@ static void removeCgroup(const std::string &cgroup_path) { } static bool initNsFromParentMem(nsjconf_t *nsjconf, pid_t pid) { - if (nsjconf->cgroup_mem_max == (size_t)0 && nsjconf->cgroup_mem_memsw_max == (size_t)0) { + ssize_t swap_max = nsjconf->cgroup_mem_swap_max; + if (nsjconf->cgroup_mem_memsw_max > (size_t)0) { + swap_max = nsjconf->cgroup_mem_memsw_max - nsjconf->cgroup_mem_max; + } + + if (nsjconf->cgroup_mem_max == (size_t)0 && swap_max < (ssize_t)0) { return true; } @@ -97,9 +102,9 @@ static bool initNsFromParentMem(nsjconf_t *nsjconf, pid_t pid) { cgroup_path, "memory.max", std::to_string(nsjconf->cgroup_mem_max))); } - if (nsjconf->cgroup_mem_memsw_max >= nsjconf->cgroup_mem_max) { - RETURN_ON_FAILURE(writeToCgroup(cgroup_path, "memory.swap.max", - std::to_string(nsjconf->cgroup_mem_memsw_max - nsjconf->cgroup_mem_max))); + if (swap_max >= (ssize_t)0) { + RETURN_ON_FAILURE( + writeToCgroup(cgroup_path, "memory.swap.max", std::to_string(swap_max))); } return true; diff --git a/cmdline.cc b/cmdline.cc index d51a1ec..1b52b33 100644 --- a/cmdline.cc +++ b/cmdline.cc @@ -143,7 +143,8 @@ 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_memsw_max", required_argument, NULL, 0x0804 }, "Maximum number of memory+swap bytes to use (default: '0' - disabled)" }, + { { "cgroup_mem_swap_max", required_argument, NULL, 0x0805 }, "Maximum number of swap bytes to use (default: '-1' - 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)" }, @@ -459,6 +460,7 @@ std::unique_ptr parseArgs(int argc, char* argv[]) { nsjconf->cgroup_mem_parent = "NSJAIL"; nsjconf->cgroup_mem_max = (size_t)0; nsjconf->cgroup_mem_memsw_max = (size_t)0; + nsjconf->cgroup_mem_swap_max = (ssize_t)-1; nsjconf->cgroup_pids_mount = "/sys/fs/cgroup/pids"; nsjconf->cgroup_pids_parent = "NSJAIL"; nsjconf->cgroup_pids_max = 0U; @@ -866,6 +868,9 @@ std::unique_ptr parseArgs(int argc, char* argv[]) { case 0x804: nsjconf->cgroup_mem_memsw_max = (size_t)strtoull(optarg, NULL, 0); break; + case 0x805: + nsjconf->cgroup_mem_swap_max = (ssize_t)strtoll(optarg, NULL, 0); + break; case 0x811: nsjconf->cgroup_pids_max = (unsigned int)strtoul(optarg, NULL, 0); break; @@ -929,6 +934,11 @@ std::unique_ptr parseArgs(int argc, char* argv[]) { } setupUsers(nsjconf.get()); + if (nsjconf->cgroup_mem_memsw_max > (size_t)0 && + nsjconf->cgroup_mem_swap_max >= (ssize_t)0) { + LOG_F("cannot set both cgroup_mem_memsw_max and cgroup_mem_swap_max"); + } + return nsjconf; } diff --git a/config.cc b/config.cc index d42d9e1..620d08e 100644 --- a/config.cc +++ b/config.cc @@ -252,6 +252,7 @@ static bool configParseInternal(nsjconf_t* nsjconf, const nsjail::NsJailConfig& nsjconf->cgroup_mem_max = njc.cgroup_mem_max(); nsjconf->cgroup_mem_memsw_max = njc.cgroup_mem_memsw_max(); + nsjconf->cgroup_mem_swap_max = njc.cgroup_mem_swap_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 49b0489..cd297ae 100644 --- a/config.proto +++ b/config.proto @@ -213,6 +213,8 @@ message NsJailConfig { 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 */ + /* If >= 0, maximum cumulative size of swap used inside any jail */ + optional int64 cgroup_mem_swap_max = 92 [default = -1]; /* 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 1222f31..4b7d4c4 100644 --- a/nsjail.1 +++ b/nsjail.1 @@ -223,6 +223,9 @@ Maximum number of bytes to use in the group (default: '0' \- disabled) \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_swap_max\fR VALUE +Maximum number of swap bytes to use in the group (default: '-1' \- 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 98c66c5..5687ca7 100644 --- a/nsjail.h +++ b/nsjail.h @@ -149,6 +149,7 @@ struct nsjconf_t { std::string cgroup_mem_parent; size_t cgroup_mem_max; size_t cgroup_mem_memsw_max; + ssize_t cgroup_mem_swap_max; std::string cgroup_pids_mount; std::string cgroup_pids_parent; unsigned int cgroup_pids_max;