diff --git a/src/limits.c b/src/limits.c index 6ccf05b06..4e8c3bd89 100644 --- a/src/limits.c +++ b/src/limits.c @@ -41,30 +41,33 @@ #include "sudo.h" -#ifndef OPEN_MAX -# define OPEN_MAX 256 +#if defined(OPEN_MAX) && OPEN_MAX > 256 +# define SUDO_OPEN_MAX OPEN_MAX +#else +# define SUDO_OPEN_MAX 256 #endif static struct saved_limit { int resource; - rlim_t fallback; bool saved; - struct rlimit limit; + rlim_t fallback; + struct rlimit newlimit; + struct rlimit oldlimit; } saved_limits[] = { #ifdef RLIMIT_AS - { RLIMIT_AS }, + { RLIMIT_AS, false, 0, { RLIM_INFINITY, RLIM_INFINITY } }, #endif - { RLIMIT_CPU }, - { RLIMIT_DATA }, - { RLIMIT_FSIZE }, - { RLIMIT_NOFILE, OPEN_MAX }, + { RLIMIT_CPU, false, 0, { RLIM_INFINITY, RLIM_INFINITY } }, + { RLIMIT_DATA, false, 0, { RLIM_INFINITY, RLIM_INFINITY } }, + { RLIMIT_FSIZE, false, 0, { RLIM_INFINITY, RLIM_INFINITY } }, + { RLIMIT_NOFILE, false, SUDO_OPEN_MAX, { RLIM_INFINITY, RLIM_INFINITY } }, #ifdef RLIMIT_NPROC - { RLIMIT_NPROC }, + { RLIMIT_NPROC, false, 0, { RLIM_INFINITY, RLIM_INFINITY } }, #endif #ifdef RLIMIT_RSS - { RLIMIT_RSS }, + { RLIMIT_RSS, false, 0, { RLIM_INFINITY, RLIM_INFINITY } }, #endif - { RLIMIT_STACK } + { RLIMIT_STACK, false, 0, { 8192 * 1024, 65532 * 1024 } } }; static struct rlimit corelimit; @@ -166,7 +169,6 @@ restore_nproc(void) void unlimit_sudo(void) { - struct rlimit inf = { RLIM_INFINITY, RLIM_INFINITY }; unsigned int idx; int rc; debug_decl(unlimit_sudo, SUDO_DEBUG_UTIL) @@ -174,24 +176,35 @@ unlimit_sudo(void) /* Set resource limits to unlimited and stash the old values. */ for (idx = 0; idx < nitems(saved_limits); idx++) { struct saved_limit *lim = &saved_limits[idx]; - if (getrlimit(lim->resource, &lim->limit) == -1) + if (getrlimit(lim->resource, &lim->oldlimit) == -1) continue; lim->saved = true; - if (setrlimit(lim->resource, &inf) == -1) { - struct rlimit rl = lim->limit; - rl.rlim_cur = MAX(rl.rlim_max, lim->fallback); - if ((rc = setrlimit(lim->resource, &rl)) == -1) { - if (lim->fallback != 0) { - /* macOS won't set rlim_cur to RLIM_INFINITY for NOFILE */ - rc = 0; - if (lim->fallback > lim->limit.rlim_cur) { - rl.rlim_cur = lim->fallback; - rc = setrlimit(lim->resource, &rl); - } - } - if (rc == -1) - sudo_warn("setrlimit(%d)", lim->resource); + if (lim->newlimit.rlim_cur != RLIM_INFINITY) { + /* Don't reduce the soft resource limit. */ + if (lim->oldlimit.rlim_cur == RLIM_INFINITY || + lim->oldlimit.rlim_cur > lim->newlimit.rlim_cur) + lim->newlimit.rlim_cur = lim->oldlimit.rlim_cur; + } + if (lim->newlimit.rlim_max != RLIM_INFINITY) { + /* Don't reduce the hard resource limit. */ + if (lim->oldlimit.rlim_max == RLIM_INFINITY || + lim->oldlimit.rlim_max > lim->newlimit.rlim_max) + lim->newlimit.rlim_max = lim->oldlimit.rlim_max; + } + if ((rc = setrlimit(lim->resource, &lim->newlimit)) == -1) { + if (lim->fallback != 0) { + /* macOS won't set rlim_cur to RLIM_INFINITY for NOFILE */ + lim->newlimit.rlim_cur = lim->fallback; + rc = setrlimit(lim->resource, &lim->newlimit); } + if (rc == -1) { + /* Try setting new rlim_cur to old rlim_max. */ + lim->newlimit.rlim_cur = lim->oldlimit.rlim_max; + lim->newlimit.rlim_max = lim->oldlimit.rlim_max; + rc = setrlimit(lim->resource, &lim->newlimit); + } + if (rc == -1) + sudo_warn("setrlimit(%d)", lim->resource); } } @@ -211,7 +224,7 @@ restore_limits(void) for (idx = 0; idx < nitems(saved_limits); idx++) { struct saved_limit *lim = &saved_limits[idx]; if (lim->saved) { - if (setrlimit(lim->resource, &lim->limit) == -1) + if (setrlimit(lim->resource, &lim->oldlimit) == -1) sudo_warn("setrlimit(%d)", lim->resource); } }