[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
19/27: Use pivot_root in addition to chroot when possible
From: |
Ludovic Courtès |
Subject: |
19/27: Use pivot_root in addition to chroot when possible |
Date: |
Wed, 03 Jun 2015 22:00:43 +0000 |
civodul pushed a commit to branch nix
in repository guix.
commit 638f3675e140af1214b82ff162baadd3ef1bb6e6
Author: Harald van Dijk <address@hidden>
Date: Fri Feb 13 16:05:49 2015 +0000
Use pivot_root in addition to chroot when possible
chroot only changes the process root directory, not the mount namespace root
directory, and it is well-known that any process with chroot capability can
break out of a chroot "jail". By using pivot_root as well, and unmounting
the
original mount namespace root directory, breaking out becomes impossible.
Non-root processes typically have no ability to use chroot() anyway, but
they
can gain that capability through the use of clone() or unshare(). For
security
reasons, these syscalls are limited in functionality when used inside a
normal
chroot environment. Using pivot_root() this way does allow those syscalls
to be
put to their full use.
---
nix/libstore/build.cc | 37 +++++++++++++++++++++++++++++--------
1 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index 43a6dd8..6276937 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -38,6 +38,9 @@
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
+#if HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
#if HAVE_SCHED_H
#include <sched.h>
#endif
@@ -48,7 +51,7 @@
#include <linux/fs.h>
#endif
-#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H &&
defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS)
+#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H &&
defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS) &&
defined(SYS_pivot_root)
#if CHROOT_ENABLED
#include <sys/socket.h>
@@ -2016,6 +2019,11 @@ void DerivationGoal::runChild()
throw SysError(format("unable to make filesystem `%1%'
private") % fs);
}
+ /* Bind-mount chroot directory to itself, to treat it as a
+ different filesystem from /, as needed for pivot_root. */
+ if (mount(chrootRootDir.c_str(), chrootRootDir.c_str(), 0,
MS_BIND, 0) == -1)
+ throw SysError(format("unable to bind mount ‘%1%’") %
chrootRootDir);
+
/* Set up a nearly empty /dev, unless the user asked to
bind-mount the host /dev. */
if (dirsInChroot.find("/dev") == dirsInChroot.end()) {
@@ -2088,13 +2096,26 @@ void DerivationGoal::runChild()
chmod_(chrootRootDir + "/dev/pts/ptmx", 0666);
}
- /* Do the chroot(). Below we do a chdir() to the
- temporary build directory to make sure the current
- directory is in the chroot. (Actually the order
- doesn't matter, since due to the bind mount tmpDir and
- tmpRootDit/tmpDir are the same directories.) */
- if (chroot(chrootRootDir.c_str()) == -1)
- throw SysError(format("cannot change root directory to `%1%'")
% chrootRootDir);
+ /* Do the chroot(). */
+ if (chdir(chrootRootDir.c_str()) == -1)
+ throw SysError(format("cannot change directory to '%1%'") %
chrootRootDir);
+
+ if (mkdir("real-root", 0) == -1)
+ throw SysError("cannot create real-root directory");
+
+#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root,
put_old))
+ if (pivot_root(".", "real-root") == -1)
+ throw SysError(format("cannot pivot old root directory onto
'%1%'") % (chrootRootDir + "/real-root"));
+#undef pivot_root
+
+ if (chroot(".") == -1)
+ throw SysError(format("cannot change root directory to '%1%'")
% chrootRootDir);
+
+ if (umount2("real-root", MNT_DETACH) == -1)
+ throw SysError("cannot unmount real root filesystem");
+
+ if (rmdir("real-root") == -1)
+ throw SysError("cannot remove real-root directory");
}
#endif
- 09/27: Better error message, (continued)
- 09/27: Better error message, Ludovic Courtès, 2015/06/03
- 10/27: Explicitly include required C headers, Ludovic Courtès, 2015/06/03
- 05/27: Ensure we're writing to stderr in the builder, Ludovic Courtès, 2015/06/03
- 12/27: libutil: Improve errmsg on readLink size mismatch., Ludovic Courtès, 2015/06/03
- 13/27: libutil: Limit readLink() error to only overflows., Ludovic Courtès, 2015/06/03
- 11/27: Pedantry, Ludovic Courtès, 2015/06/03
- 14/27: Set /nix/store permission to 1737, Ludovic Courtès, 2015/06/03
- 16/27: Doh^2, Ludovic Courtès, 2015/06/03
- 17/27: Simplify printHash32, Ludovic Courtès, 2015/06/03
- 18/27: Simplify parseHash32, Ludovic Courtès, 2015/06/03
- 19/27: Use pivot_root in addition to chroot when possible,
Ludovic Courtès <=
- 15/27: Doh, Ludovic Courtès, 2015/06/03
- 22/27: Tighten permissions on chroot directories, Ludovic Courtès, 2015/06/03
- 20/27: Use chroots for all derivations, Ludovic Courtès, 2015/06/03
- 25/27: Revert /nix/store permission back to 01775, Ludovic Courtès, 2015/06/03
- 21/27: Fix typos: s/the the/the/, Ludovic Courtès, 2015/06/03
- 24/27: Chroot builds: Provide world-readable /nix/store, Ludovic Courtès, 2015/06/03
- 23/27: addToStore(): Take explicit name argument, Ludovic Courtès, 2015/06/03
- 27/27: Don't let unprivileged users repair paths, Ludovic Courtès, 2015/06/03
- 26/27: Add a ‘verifyStore’ RPC, Ludovic Courtès, 2015/06/03