From: Todd C. Miller Date: Fri, 12 Jun 2015 21:30:06 +0000 (-0600) Subject: We need to unlimit RLIMIT_NPROC in sudoers as well as the sudo front X-Git-Tag: SUDO_1_8_14^2~93 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=25917e435c3b677c71e4ab0d5821328db8227b5f;p=sudo We need to unlimit RLIMIT_NPROC in sudoers as well as the sudo front end since set_perms() and restore_perms change the read uid and may fail with EAGAIN on Linux kernels prior to 3.1. --- diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 8d6b1db7c..981c66e1d 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -110,10 +111,54 @@ static char *runas_user; static char *runas_group; static struct sudo_nss_list *snl; +#ifdef __linux__ +static struct rlimit nproclimit; +#endif + /* XXX - must be extern for audit bits of sudo_auth.c */ int NewArgc; char **NewArgv; +/* + * Unlimit the number of processes since Linux's setuid() will + * apply resource limits when changing uid and return EAGAIN if + * nproc would be exceeded by the uid switch. + */ +static void +unlimit_nproc(void) +{ +#ifdef __linux__ + struct rlimit rl; + debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL) + + if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0) + sudo_warn("getrlimit"); + rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_NPROC, &rl) != 0) { + rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max; + if (setrlimit(RLIMIT_NPROC, &rl) != 0) + sudo_warn("setrlimit"); + } + debug_return; +#endif /* __linux__ */ +} + +/* + * Restore saved value of RLIMIT_NPROC. + */ +static void +restore_nproc(void) +{ +#ifdef __linux__ + debug_decl(restore_nproc, SUDO_DEBUG_UTIL) + + if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0) + sudo_warn("setrlimit"); + + debug_return; +#endif /* __linux__ */ +} + int sudoers_policy_init(void *info, char * const envp[]) { @@ -232,6 +277,8 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], sudo_warn_set_locale_func(sudoers_warn_setlocale); + unlimit_nproc(); + /* Is root even allowed to run sudo? */ if (user_uid == 0 && !def_root_sudo) { /* Not an audit event. */ @@ -558,6 +605,8 @@ done: if (!rewind_perms()) rval = -1; + restore_nproc(); + /* Close the password and group files and free up memory. */ sudo_endpwent(); sudo_endgrent(); diff --git a/src/sudo.c b/src/sudo.c index 5d7511ec7..f509e4beb 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -829,12 +829,13 @@ unlimit_nproc(void) struct rlimit rl; debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL) - (void) getrlimit(RLIMIT_NPROC, &nproclimit); + if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0) + sudo_warn("getrlimit"); rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_NPROC, &rl) != 0) { - memcpy(&rl, &nproclimit, sizeof(struct rlimit)); - rl.rlim_cur = rl.rlim_max; - (void)setrlimit(RLIMIT_NPROC, &rl); + rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max; + if (setrlimit(RLIMIT_NPROC, &rl) != 0) + sudo_warn("setrlimit"); } debug_return; #endif /* __linux__ */ @@ -849,7 +850,8 @@ restore_nproc(void) #ifdef __linux__ debug_decl(restore_nproc, SUDO_DEBUG_UTIL) - (void) setrlimit(RLIMIT_NPROC, &nproclimit); + if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0) + sudo_warn("setrlimit"); debug_return; #endif /* __linux__ */