]> granicus.if.org Git - sudo/commitdiff
We need to unlimit RLIMIT_NPROC in sudoers as well as the sudo front
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 12 Jun 2015 21:30:06 +0000 (15:30 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 12 Jun 2015 21:30:06 +0000 (15:30 -0600)
end since set_perms() and restore_perms change the read uid and may
fail with EAGAIN on Linux kernels prior to 3.1.

plugins/sudoers/sudoers.c
src/sudo.c

index 8d6b1db7c4bf9a59ef2e84f22ca222dac49b270c..981c66e1dfc1f4bba2046d0b68b1ffd08ec423f7 100644 (file)
@@ -27,6 +27,7 @@
 #include <config.h>
 
 #include <sys/types.h>
+#include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <stdio.h>
@@ -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();
index 5d7511ec73fc58e847d57c0dbb72349cf8f35624..f509e4bebca9b8c5f39c50b1846fad9ce84087b0 100644 (file)
@@ -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__ */