summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2012-08-10 15:07:42 -0400
committerColin Walters <walters@verbum.org>2012-08-10 15:07:42 -0400
commitce49cffb83d35e550c16b7aee23fac262e6f359d (patch)
treeb78a5a641e198975a082f3e50cad7f0417fec6c6
parent92457a2b2c29bba0ee272b7f86704ca10f44fd55 (diff)
downloadlinux-user-chroot-ce49cffb83d35e550c16b7aee23fac262e6f359d.tar.gz
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/
-rw-r--r--src/linux-user-chroot.c30
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)");