Add minimum value to consider when overriding resource limits.

Currently only used for RLIMIT_DATA and RLIMIT_AS.

This works around a problem on HP-UX where setting RLIMIT_DATA
changes the resource limits for both 32-bit and 64-bit processes.
HP-UX processes start out with RLIMIT_DATA set based on the values
of the maxdsiz and maxdsiz_64bit kernel tunables, depending on
whether they are 32-bit or 64-bit.  By default this limit is 1GB
for 32-bit processes and 4GB for 64-bit.  However, once RLIMIT_DATA
is changed, it does not appear to be possible to restore the old
values.  This can result in a 64-bit process that is executed by a
32-bit shell getting the 32-bit RLIMIT_DATA instead of the 64-bit
one.  Bug #973
This commit is contained in:
Todd C. Miller
2021-04-20 14:31:40 -06:00
parent 32f742389b
commit 6717415e73

View File

@@ -74,31 +74,108 @@ static struct saved_limit {
int resource; /* RLIMIT_FOO definition */ int resource; /* RLIMIT_FOO definition */
bool override; /* override limit while sudo executes? */ bool override; /* override limit while sudo executes? */
bool saved; /* true if we were able to get the value */ bool saved; /* true if we were able to get the value */
rlim_t minlimit; /* only modify limit if less than this value */
struct rlimit *fallback; /* fallback if we fail to set to newlimit */ struct rlimit *fallback; /* fallback if we fail to set to newlimit */
struct rlimit newlimit; /* new limit to use if override is true */ struct rlimit newlimit; /* new limit to use if override is true */
struct rlimit oldlimit; /* original limit, valid if saved is true */ struct rlimit oldlimit; /* original limit, valid if saved is true */
} saved_limits[] = { } saved_limits[] = {
#ifdef RLIMIT_AS #ifdef RLIMIT_AS
{ "rlimit_as", RLIMIT_AS, true, false, NULL, { RLIM_INFINITY, RLIM_INFINITY } }, {
"rlimit_as",
RLIMIT_AS,
true, /* override */
false, /* saved */
1 * 1024 * 1024 * 1024, /* minlimit */
NULL, /* fallback */
{ RLIM_INFINITY, RLIM_INFINITY } /* newlimit */
},
#endif #endif
{ "rlimit_core", RLIMIT_CORE, false }, {
{ "rlimit_cpu", RLIMIT_CPU, true, false, NULL, { RLIM_INFINITY, RLIM_INFINITY } }, "rlimit_core",
{ "rlimit_data", RLIMIT_DATA, true, false, NULL, { RLIM_INFINITY, RLIM_INFINITY } }, RLIMIT_CORE,
{ "rlimit_fsize", RLIMIT_FSIZE, true, false, NULL, { RLIM_INFINITY, RLIM_INFINITY } }, false /* override */
},
{
"rlimit_cpu",
RLIMIT_CPU,
true, /* override */
false, /* saved */
RLIM_INFINITY, /* minlimit */
NULL,
{ RLIM_INFINITY, RLIM_INFINITY }
},
{
"rlimit_data",
RLIMIT_DATA,
true, /* override */
false, /* saved */
1 * 1024 * 1024 * 1024, /* minlimit */
NULL,
{ RLIM_INFINITY, RLIM_INFINITY }
},
{
"rlimit_fsize",
RLIMIT_FSIZE,
true, /* override */
false, /* saved */
RLIM_INFINITY, /* minlimit */
NULL,
{ RLIM_INFINITY, RLIM_INFINITY }
},
#ifdef RLIMIT_LOCKS #ifdef RLIMIT_LOCKS
{ "rlimit_locks", RLIMIT_LOCKS, false }, {
"rlimit_locks",
RLIMIT_LOCKS,
false /* override */
},
#endif #endif
#ifdef RLIMIT_MEMLOCK #ifdef RLIMIT_MEMLOCK
{ "rlimit_memlock", RLIMIT_MEMLOCK, false }, {
"rlimit_memlock",
RLIMIT_MEMLOCK,
false /* override */
},
#endif #endif
{ "rlimit_nofile", RLIMIT_NOFILE, true, false, &nofile_fallback, { RLIM_INFINITY, RLIM_INFINITY } }, {
"rlimit_nofile",
RLIMIT_NOFILE,
true, /* override */
false, /* saved */
RLIM_INFINITY, /* minlimit */
&nofile_fallback,
{ RLIM_INFINITY, RLIM_INFINITY }
},
#ifdef RLIMIT_NPROC #ifdef RLIMIT_NPROC
{ "rlimit_nproc", RLIMIT_NPROC, true, false, NULL, { RLIM_INFINITY, RLIM_INFINITY } }, {
"rlimit_nproc",
RLIMIT_NPROC,
true, /* override */
false, /* saved */
RLIM_INFINITY, /* minlimit */
NULL,
{ RLIM_INFINITY, RLIM_INFINITY }
},
#endif #endif
#ifdef RLIMIT_RSS #ifdef RLIMIT_RSS
{ "rlimit_rss", RLIMIT_RSS, true, false, NULL, { RLIM_INFINITY, RLIM_INFINITY } }, {
"rlimit_rss",
RLIMIT_RSS,
true, /* override */
false, /* saved */
RLIM_INFINITY, /* minlimit */
NULL,
{ RLIM_INFINITY, RLIM_INFINITY }
},
#endif #endif
{ "rlimit_stack", RLIMIT_STACK, true, false, &stack_fallback, { SUDO_STACK_MIN, RLIM_INFINITY } } {
"rlimit_stack",
RLIMIT_STACK,
true, /* override */
false, /* saved */
RLIM_INFINITY, /* minlimit */
&stack_fallback,
{ SUDO_STACK_MIN, RLIM_INFINITY }
}
}; };
static struct rlimit corelimit; static struct rlimit corelimit;
@@ -237,14 +314,19 @@ unlimit_sudo(void)
if (getrlimit(lim->resource, &lim->oldlimit) == -1) if (getrlimit(lim->resource, &lim->oldlimit) == -1)
continue; continue;
sudo_debug_printf(SUDO_DEBUG_INFO, sudo_debug_printf(SUDO_DEBUG_INFO,
"getrlimit(lim->name) -> [%lld, %lld]", "getrlimit(%s) -> [%lld, %lld]", lim->name,
(long long)lim->oldlimit.rlim_cur, (long long)lim->oldlimit.rlim_cur,
(long long)lim->oldlimit.rlim_max); (long long)lim->oldlimit.rlim_max);
lim->saved = true; lim->saved = true;
/* Only override the existing limit if it is smaller than minlimit. */
if (lim->minlimit != RLIM_INFINITY) {
if (lim->oldlimit.rlim_cur >= lim->minlimit)
lim->override = false;
}
if (!lim->override) if (!lim->override)
continue; continue;
if (lim->newlimit.rlim_cur != RLIM_INFINITY) { if (lim->newlimit.rlim_cur != RLIM_INFINITY) {
/* Don't reduce the soft resource limit. */ /* Don't reduce the soft resource limit. */
if (lim->oldlimit.rlim_cur == RLIM_INFINITY || if (lim->oldlimit.rlim_cur == RLIM_INFINITY ||