From 29d35805c63f316aa19b33a481f953ca332d9b65 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 31 Mar 2017 18:12:01 +0200 Subject: [PATCH] Sandbox: Fix /dev/ptmx on recent kernels This fixes "No such file or directory" when opening /dev/ptmx (e.g. http://hydra.nixos.org/build/51094249). The reason appears to be some changes to /dev/ptmx / /dev/pts handling between Linux 4.4 and 4.9. See https://patchwork.kernel.org/patch/7832531/. The fix is to go back to mounting a proper /dev/pts instance inside the sandbox. Happily, this now works inside user namespaces, even for unprivileged users. So NIX_REMOTE=local?root=/tmp/nix nix-build \ '' -A test works for non-root users. The downside is that the fix breaks sandbox builds on older kernels (probably pre-4.6), since mounting a devpts fails inside user namespaces for some reason I've never been able to figure out. Builds on those systems will fail with error: while setting up the build environment: mounting /dev/pts: Invalid argument Ah well. --- src/libstore/build.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index fc840df81..43a8dadf8 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -2391,8 +2391,6 @@ void DerivationGoal::runChild() ss.push_back("/dev/tty"); ss.push_back("/dev/urandom"); ss.push_back("/dev/zero"); - ss.push_back("/dev/ptmx"); - ss.push_back("/dev/pts"); createSymlink("/proc/self/fd", chrootRootDir + "/dev/fd"); createSymlink("/proc/self/fd/0", chrootRootDir + "/dev/stdin"); createSymlink("/proc/self/fd/1", chrootRootDir + "/dev/stdout"); @@ -2448,17 +2446,13 @@ void DerivationGoal::runChild() fmt("size=%s", settings.get("sandbox-dev-shm-size", std::string("50%"))).c_str()) == -1) throw SysError("mounting /dev/shm"); -#if 0 - // FIXME: can't figure out how to do this in a user - // namespace. - /* Mount a new devpts on /dev/pts. Note that this requires the kernel to be compiled with CONFIG_DEVPTS_MULTIPLE_INSTANCES=y (which is the case if /dev/ptx/ptmx exists). */ if (pathExists("/dev/pts/ptmx") && !pathExists(chrootRootDir + "/dev/ptmx") - && dirsInChroot.find("/dev/pts") == dirsInChroot.end()) + && !dirsInChroot.count("/dev/pts")) { if (mount("none", (chrootRootDir + "/dev/pts").c_str(), "devpts", 0, "newinstance,mode=0620") == -1) throw SysError("mounting /dev/pts"); @@ -2468,7 +2462,6 @@ void DerivationGoal::runChild() Linux versions, it is created with permissions 0. */ chmod_(chrootRootDir + "/dev/pts/ptmx", 0666); } -#endif /* Do the chroot(). */ if (chdir(chrootRootDir.c_str()) == -1)