diff -up sudo-1.8.6p3/src/exec.c.nprocfix sudo-1.8.6p3/src/exec.c --- sudo-1.8.6p3/src/exec.c.nprocfix 2013-07-11 12:55:10.686308050 +0200 +++ sudo-1.8.6p3/src/exec.c 2013-07-11 12:54:21.159160553 +0200 @@ -132,6 +132,15 @@ static int fork_cmnd(struct command_deta if (policy_init_session(details) != true) errorx(1, _("policy plugin failed session initialization")); + /* + * See the comment in unlimit_nproc. It is important to call + * this function AFTER policy_init_session, because the PAM + * subsystem, if used, may change the RLIMIT_NPROC limit to + * unlimited (infinity) and we would not be able to distinguish + * between our temporary change and the change done by PAM. + */ + unlimit_nproc(); + cmnd_pid = sudo_debug_fork(); switch (cmnd_pid) { case -1: diff -up sudo-1.8.6p3/src/exec_pty.c.nprocfix sudo-1.8.6p3/src/exec_pty.c --- sudo-1.8.6p3/src/exec_pty.c.nprocfix 2012-09-18 15:57:43.000000000 +0200 +++ sudo-1.8.6p3/src/exec_pty.c 2013-07-11 12:37:41.811202301 +0200 @@ -678,6 +678,15 @@ fork_pty(struct command_details *details errorx(1, _("policy plugin failed session initialization")); /* + * See the comment in unlimit_nproc. It is important to call + * this function AFTER policy_init_session, because the PAM + * subsystem, if used, may change the RLIMIT_NPROC limit to + * unlimited (infinity) and we would not be able to distinguish + * between our temporary change and the change done by PAM. + */ + unlimit_nproc(); + + /* * Block some signals until cmnd_pid is set in the parent to avoid a * race between exec of the command and receipt of a fatal signal from it. */ diff -up sudo-1.8.6p3/src/sudo.c.nprocfix sudo-1.8.6p3/src/sudo.c --- sudo-1.8.6p3/src/sudo.c.nprocfix 2013-07-11 12:37:41.767202170 +0200 +++ sudo-1.8.6p3/src/sudo.c 2013-07-11 12:37:41.811202301 +0200 @@ -808,25 +808,11 @@ sudo_check_suid(const char *path) static void disable_coredumps(void) { -#if defined(__linux__) || defined(RLIMIT_CORE) - struct rlimit rl; +#if defined(RLIMIT_CORE) + struct rlimit rl; #endif debug_decl(disable_coredumps, SUDO_DEBUG_UTIL) -#if defined(__linux__) - /* - * Unlimit the number of processes since Linux's setuid() will - * apply resource limits when changing uid and return EAGAIN if - * nproc would be violated by the uid switch. - */ - (void) getrlimit(RLIMIT_NPROC, &nproclimit); - rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; - if (setrlimit(RLIMIT_NPROC, &rl)) { - memcpy(&rl, &nproclimit, sizeof(struct rlimit)); - rl.rlim_cur = rl.rlim_max; - (void)setrlimit(RLIMIT_NPROC, &rl); - } -#endif /* __linux__ */ #ifdef RLIMIT_CORE /* * Turn off core dumps? @@ -841,6 +827,28 @@ disable_coredumps(void) debug_return; } +void +unlimit_nproc(void) +{ + debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL) +#if defined(__linux__) + struct rlimit rl; + /* + * Unlimit the number of processes since Linux's setuid() will + * apply resource limits when changing uid and return EAGAIN if + * nproc would be violated by the uid switch. + */ + (void) getrlimit(RLIMIT_NPROC, &nproclimit); + rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_NPROC, &rl)) { + memcpy(&rl, &nproclimit, sizeof(struct rlimit)); + rl.rlim_cur = rl.rlim_max; + (void)setrlimit(RLIMIT_NPROC, &rl); + } +#endif /* __linux__ */ + debug_return; +} + #ifdef HAVE_PROJECT_H static void set_project(struct passwd *pw) @@ -1082,7 +1090,6 @@ exec_setup(struct command_details *detai errno = 0; l = sysconf(_SC_CHILD_MAX); if (l == -1 && errno == 0 && getrlimit(RLIMIT_NPROC, &rl) == 0) { - if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY) (void) setrlimit(RLIMIT_NPROC, &nproclimit); } } diff -up sudo-1.8.6p3/src/sudo.h.nprocfix sudo-1.8.6p3/src/sudo.h --- sudo-1.8.6p3/src/sudo.h.nprocfix 2013-07-11 12:37:41.768202173 +0200 +++ sudo-1.8.6p3/src/sudo.h 2013-07-11 12:37:41.811202301 +0200 @@ -219,6 +219,7 @@ int policy_init_session(struct command_d int run_command(struct command_details *details); extern const char *list_user, *runas_user, *runas_group; extern struct user_details user_details; +void unlimit_nproc(void); /* sudo_edit.c */ int sudo_edit(struct command_details *details);