[linux-user-chroot] Make use of PR_SET_NO_NEW_PRIVS if available



commit ce49cffb83d35e550c16b7aee23fac262e6f359d
Author: Colin Walters <walters verbum org>
Date:   Fri Aug 10 15:07:42 2012 -0400

    Make use of PR_SET_NO_NEW_PRIVS if available
    
    This flag is exactly what we want for this tool (it's what I thought
    SECBIT_NOROOT did).
    
    See the linked discussion from here:
    
    http://lwn.net/Articles/504879/

 src/linux-user-chroot.c |   30 ++++++++++++++++++++----------
 1 files changed, 20 insertions(+), 10 deletions(-)
---
diff --git a/src/linux-user-chroot.c b/src/linux-user-chroot.c
index 7c2e678..3d5700c 100644
--- a/src/linux-user-chroot.c
+++ b/src/linux-user-chroot.c
@@ -5,7 +5,8 @@
  * "safely": I believe that this program, when deployed as setuid on a
  * typical "distribution" such as RHEL or Debian, does not, even when
  * used in combination with typical software installed on that
- * distribution, allow privilege escalation.
+ * distribution, allow privilege escalation.  See the README for more
+ * details.
  *
  * Copyright 2011,2012 Colin Walters <walters verbum org>
  *
@@ -30,6 +31,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <fcntl.h>
+#include <errno.h>
 #include <stdarg.h>
 #include <string.h>
 #include <assert.h>
@@ -47,6 +49,10 @@
 #define SECBIT_NOROOT_LOCKED (1 << 1)
 #endif
 
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS	38
+#endif
+
 static void fatal (const char *message, ...) __attribute__ ((noreturn)) __attribute__ ((format (printf, 1, 2)));
 static void fatal_errno (const char *message) __attribute__ ((noreturn));
 
@@ -274,16 +280,20 @@ main (int      argc,
   if (child == 0)
     {
       /*
-       * SECBIT_NOROOT helps close the main historical reason why only
-       * uid 0 can chroot(2) - because unprivileged users can create
-       * hard links to setuid binaries, and possibly confuse them into
-       * looking at data (or loading libraries) that they don't
-       * expect, and thus elevating privileges.  With this, executing
-       * a setuid program doesn't gain us any new Linux capabilities
-       * (but it still changes uid).  See below for where we create a
-       * MS_NOSUID bind mount.
+       * First, we attempt to use PR_SET_NO_NEW_PRIVS, since it does
+       * exactly what we want - ensures the child can not gain any
+       * privileges, even attempting to execute setuid binaries.
+       *
+       * http://lwn.net/Articles/504879/
+       *
+       * If that's not available, we fall back to using SECBIT_NOROOT.
+       *
+       * Following the belt-and-suspenders model, we also make a
+       * MS_NOSUID bind mount below.
        */
-      if (prctl (PR_SET_SECUREBITS,
+      if (prctl (PR_SET_NO_NEW_PRIVS, 1) < 0 && errno != EINVAL)
+        fatal_errno ("prctl (PR_SET_NO_NEW_PRIVS)");
+      else if (prctl (PR_SET_SECUREBITS,
                  SECBIT_NOROOT | SECBIT_NOROOT_LOCKED) < 0)
         fatal_errno ("prctl (SECBIT_NOROOT)");
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]