|
38 | 38 | #if HAVE_SYS_MOUNT_H
|
39 | 39 | #include <sys/mount.h>
|
40 | 40 | #endif
|
| 41 | +#if HAVE_SYS_SYSCALL_H |
| 42 | +#include <sys/syscall.h> |
| 43 | +#endif |
41 | 44 | #if HAVE_SCHED_H
|
42 | 45 | #include <sched.h>
|
43 | 46 | #endif
|
|
48 | 51 | #include <linux/fs.h>
|
49 | 52 | #endif
|
50 | 53 |
|
51 |
| -#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS) |
| 54 | +#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS) && defined(SYS_pivot_root) |
52 | 55 |
|
53 | 56 | /* chroot-like behavior from Apple's sandbox */
|
54 | 57 | #if __APPLE__
|
@@ -2059,6 +2062,11 @@ void DerivationGoal::runChild()
|
2059 | 2062 | throw SysError(format("unable to make filesystem ‘%1%’ private") % fs);
|
2060 | 2063 | }
|
2061 | 2064 |
|
| 2065 | + /* Bind-mount chroot directory to itself, to treat it as a |
| 2066 | + different filesystem from /, as needed for pivot_root. */ |
| 2067 | + if (mount(chrootRootDir.c_str(), chrootRootDir.c_str(), 0, MS_BIND, 0) == -1) |
| 2068 | + throw SysError(format("unable to bind mount ‘%1%’") % chrootRootDir); |
| 2069 | + |
2062 | 2070 | /* Set up a nearly empty /dev, unless the user asked to
|
2063 | 2071 | bind-mount the host /dev. */
|
2064 | 2072 | if (dirsInChroot.find("/dev") == dirsInChroot.end()) {
|
@@ -2130,13 +2138,26 @@ void DerivationGoal::runChild()
|
2130 | 2138 | chmod_(chrootRootDir + "/dev/pts/ptmx", 0666);
|
2131 | 2139 | }
|
2132 | 2140 |
|
2133 |
| - /* Do the chroot(). Below we do a chdir() to the |
2134 |
| - temporary build directory to make sure the current |
2135 |
| - directory is in the chroot. (Actually the order |
2136 |
| - doesn't matter, since due to the bind mount tmpDir and |
2137 |
| - tmpRootDit/tmpDir are the same directories.) */ |
2138 |
| - if (chroot(chrootRootDir.c_str()) == -1) |
| 2141 | + /* Do the chroot(). */ |
| 2142 | + if (chdir(chrootRootDir.c_str()) == -1) |
| 2143 | + throw SysError(format("cannot change directory to ‘%1%’") % chrootRootDir); |
| 2144 | + |
| 2145 | + if (mkdir("real-root", 0) == -1) |
| 2146 | + throw SysError("cannot create real-root directory"); |
| 2147 | + |
| 2148 | +#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old)) |
| 2149 | + if (pivot_root(".", "real-root") == -1) |
| 2150 | + throw SysError(format("cannot pivot old root directory onto ‘%1%’") % (chrootRootDir + "/real-root")); |
| 2151 | +#undef pivot_root |
| 2152 | + |
| 2153 | + if (chroot(".") == -1) |
2139 | 2154 | throw SysError(format("cannot change root directory to ‘%1%’") % chrootRootDir);
|
| 2155 | + |
| 2156 | + if (umount2("real-root", MNT_DETACH) == -1) |
| 2157 | + throw SysError("cannot unmount real root filesystem"); |
| 2158 | + |
| 2159 | + if (rmdir("real-root") == -1) |
| 2160 | + throw SysError("cannot remove real-root directory"); |
2140 | 2161 | }
|
2141 | 2162 | #endif
|
2142 | 2163 |
|
|
0 commit comments