diff --git a/cmdline.c b/cmdline.c index 9f42786..f7c35ba 100644 --- a/cmdline.c +++ b/cmdline.c @@ -257,11 +257,14 @@ __rlim64_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul) if (getrlimit64(res, &cur) == -1) { PLOG_F("getrlimit(%d)", res); } - if (strcasecmp(optarg, "max") == 0) { + if (strcasecmp(optarg, "def") == 0 || strcasecmp(optarg, "soft") == 0) { + return cur.rlim_cur; + } + if (strcasecmp(optarg, "max") == 0 || strcasecmp(optarg, "hard")) { return cur.rlim_max; } - if (strcasecmp(optarg, "def") == 0) { - return cur.rlim_cur; + if (strcasecmp(optarg, "inf") == 0) { + return RLIM64_INFINITY; } if (utilIsANumber(optarg) == false) { LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, diff --git a/config.cc b/config.cc index c6c84ff..4d13176 100644 --- a/config.cc +++ b/config.cc @@ -30,6 +30,7 @@ extern "C" { #include #include "caps.h" +#include "cmdline.h" #include "config.h" #include "log.h" #include "mount.h" @@ -46,6 +47,24 @@ extern "C" { #define DUP_IF_SET(njc, val) (njc.has_##val() ? utilStrDup(njc.val().c_str()) : NULL) +static __rlim64_t configRLimit(int res, const nsjail::RLimit& rl, const uint64_t val, unsigned long mul = 1UL) +{ + if (rl == nsjail::RLimit::VALUE) { + return (val * mul); + } + if (rl == nsjail::RLimit::SOFT) { + return cmdlineParseRLimit(res, "soft", mul); + } + if (rl == nsjail::RLimit::HARD) { + return cmdlineParseRLimit(res, "hard", mul); + } + if (rl == nsjail::RLimit::INF) { + return RLIM64_INFINITY; + } + LOG_F("Unknown rlimit value type for rlimit:%d", res); + abort(); +} + static bool configParseInternal(struct nsjconf_t* nsjconf, const nsjail::NsJailConfig& njc) { @@ -138,17 +157,13 @@ static bool configParseInternal(struct nsjconf_t* nsjconf, nsjconf->disable_no_new_privs = njc.disable_no_new_privs(); - nsjconf->rl_as = njc.rlimit_as() * 1024ULL * 1024ULL; - nsjconf->rl_core = njc.rlimit_core() * 1024ULL * 1024ULL; - nsjconf->rl_cpu = njc.rlimit_cpu(); - nsjconf->rl_fsize = njc.rlimit_fsize() * 1024ULL * 1024ULL; - nsjconf->rl_nofile = njc.rlimit_nofile(); - if (njc.has_rlimit_nproc()) { - nsjconf->rl_nproc = njc.rlimit_nproc(); - } - if (njc.has_rlimit_stack()) { - nsjconf->rl_stack = njc.rlimit_stack() * 1024ULL * 1024ULL; - } + nsjconf->rl_as = configRLimit(RLIMIT_AS, njc.rlimit_as_type(), njc.rlimit_as(), 1024UL * 1024UL); + nsjconf->rl_core = configRLimit(RLIMIT_CORE, njc.rlimit_core_type(), njc.rlimit_core(), 1024UL * 1024UL); + nsjconf->rl_cpu = configRLimit(RLIMIT_CPU, njc.rlimit_cpu_type(), njc.rlimit_cpu()); + nsjconf->rl_fsize = configRLimit(RLIMIT_FSIZE, njc.rlimit_fsize_type(), njc.rlimit_fsize(), 1024UL * 1024UL); + nsjconf->rl_nofile = configRLimit(RLIMIT_NOFILE, njc.rlimit_nofile_type(), njc.rlimit_nofile()); + nsjconf->rl_nproc = configRLimit(RLIMIT_NPROC, njc.rlimit_nproc_type(), njc.rlimit_nproc()); + nsjconf->rl_stack = configRLimit(RLIMIT_STACK, njc.rlimit_stack_type(), njc.rlimit_stack(), 1024UL * 1024UL); if (njc.persona_addr_compat_layout()) { nsjconf->personality |= ADDR_COMPAT_LAYOUT; diff --git a/config.proto b/config.proto index e23c29d..b7e8c7e 100644 --- a/config.proto +++ b/config.proto @@ -54,6 +54,12 @@ message MountPt /* Is it a symlink (instead of real mount point)? */ optional bool is_symlink = 12 [ default = false ]; } +enum RLimit { + VALUE = 0; /* Use the provided value */ + SOFT = 1; /* Use current soft rlimit */ + HARD = 2; /* Use current hard rlimit */ + INF = 3; /* Use RLIM64_INFINITY */ +} message Exe { /* Will be used both as execv's path and as argv[0] */ @@ -126,13 +132,24 @@ message NsJailConfig inside the jail */ optional bool disable_no_new_privs = 25 [ default = false ]; + /* Various rlimits, the rlimit_as/rlimit_core/... are used only if + rlimit_as_type/rlimit_core_type/... are set to RLimit::VALUE */ optional uint64 rlimit_as = 26 [ default = 512 ]; /* In MiB */ + optional RLimit rlimit_as_type = 64 [ default = VALUE ]; optional uint64 rlimit_core = 27 [ default = 0 ]; /* In MiB */ + optional RLimit rlimit_core_type = 65 [ default = VALUE ]; optional uint64 rlimit_cpu = 28 [ default = 600 ]; /* In seconds */ + optional RLimit rlimit_cpu_type = 66 [ default = VALUE ]; optional uint64 rlimit_fsize = 29 [ default = 1 ]; /* In MiB */ + optional RLimit rlimit_fsize_type = 67 [ default = VALUE ]; optional uint64 rlimit_nofile = 30 [ default = 32 ]; - optional uint64 rlimit_nproc = 31; /* This is system-wide: tricky to use */ - optional uint64 rlimit_stack = 32; /* In MiB */ + optional RLimit rlimit_nofile_type = 68 [ default = VALUE ]; + /* RLIMIT_NPROC is system-wide - tricky to use; use the soft limit value by default here */ + optional uint64 rlimit_nproc = 31 [ default = 1024 ]; + optional RLimit rlimit_nproc_type = 69 [ default = SOFT ]; + /* In MiB, use the soft limit value by default */ + optional uint64 rlimit_stack = 32 [ default = 1048576 ]; + optional RLimit rlimit_stack_type = 70 [ default = SOFT ]; /* See 'man personality' for more */ optional bool persona_addr_compat_layout = 33 [ default = false ]; diff --git a/configs/bash-with-fake-geteuid.cfg b/configs/bash-with-fake-geteuid.cfg index 1f4cae7..9241af5 100644 --- a/configs/bash-with-fake-geteuid.cfg +++ b/configs/bash-with-fake-geteuid.cfg @@ -40,7 +40,8 @@ rlimit_core: 0 rlimit_cpu: 10 rlimit_fsize: 0 rlimit_nofile: 32 -rlimit_stack: 1 +rlimit_stack_type: SOFT +rlimit_nproc_type: SOFT persona_addr_compat_layout: false persona_mmap_page_zero: false diff --git a/contain.h b/contain.h index 31c8714..edba108 100644 --- a/contain.h +++ b/contain.h @@ -26,7 +26,7 @@ #include "common.h" -bool containSetupFD(struct nsjconf_t * nsjconf, int fd_in, int fd_out, int fd_err); +bool containSetupFD(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_err); bool containContain(struct nsjconf_t *nsjconf); #endif /* NS_CONTAIN_H */