Loading pkgs/tools/package-management/nix/common.nix +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ let atLeast210 = lib.versionAtLeast version "2.10pre"; atLeast213 = lib.versionAtLeast version "2.13pre"; atLeast214 = lib.versionAtLeast version "2.14pre"; atLeast218 = lib.versionAtLeast version "2.18pre"; atLeast219 = lib.versionAtLeast version "2.19pre"; atLeast220 = lib.versionAtLeast version "2.20pre"; atLeast221 = lib.versionAtLeast version "2.21pre"; Loading @@ -42,6 +43,7 @@ in , callPackage , coreutils , curl , darwin , docbook_xsl_ns , docbook5 , editline Loading Loading @@ -158,6 +160,8 @@ self = stdenv.mkDerivation { libseccomp ] ++ lib.optionals withAWS [ aws-sdk-cpp ] ++ lib.optional (atLeast218 && stdenv.hostPlatform.isDarwin) [ darwin.apple_sdk.libs.sandbox ]; Loading pkgs/tools/package-management/nix/default.nix +51 −0 Original line number Diff line number Diff line Loading @@ -178,42 +178,85 @@ in lib.makeExtensible (self: ({ version = "2.18.8"; hash = "sha256-0rHRifdjzzxMh/im8pRx6XoY62irDTDUes+Pn0CR65I="; self_attribute_name = "nix_2_18"; patches = [ ./patches/2_18/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_18/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_18/0003-local-derivation-goal-Refactor.patch ./patches/2_18/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_19 = common { version = "2.19.6"; hash = "sha256-XT5xiwOLgXf+TdyOjbJVOl992wu9mBO25WXHoyli/Tk="; self_attribute_name = "nix_2_19"; patches = [ ./patches/2_19/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_19/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_19/0003-local-derivation-goal-Refactor.patch ./patches/2_19/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_20 = common { version = "2.20.8"; hash = "sha256-M2tkMtjKi8LDdNLsKi3IvD8oY/i3rtarjMpvhybS3WY="; self_attribute_name = "nix_2_20"; patches = [ ./patches/2_20/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_20/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_20/0003-local-derivation-goal-Refactor.patch ./patches/2_20/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_21 = common { version = "2.21.4"; hash = "sha256-c6nVZ0pSrfhFX3eVKqayS+ioqyAGp3zG9ZPO5rkXFRQ="; self_attribute_name = "nix_2_21"; patches = [ ./patches/2_21/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_21/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_21/0003-local-derivation-goal-Refactor.patch ./patches/2_21/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_22 = common { version = "2.22.3"; hash = "sha256-l04csH5rTWsK7eXPWVxJBUVRPMZXllFoSkYFTq/i8WU="; self_attribute_name = "nix_2_22"; patches = [ ./patches/2_22/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_22/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_22/0003-local-derivation-goal-Refactor.patch ./patches/2_22/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_23 = common { version = "2.23.3"; hash = "sha256-lAoLGVIhRFrfgv7wcyduEkyc83QKrtsfsq4of+WrBeg="; self_attribute_name = "nix_2_23"; patches = [ ./patches/2_23/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_23/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_23/0003-local-derivation-goal-Refactor.patch ./patches/2_23/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_24 = (common { version = "2.24.9"; hash = "sha256-OwJByTdCz1t91ysBqynK+ifszkoIGEXUn6HE2t82+c8="; self_attribute_name = "nix_2_24"; patches = [ ./patches/2_24/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_24/0002-packaging-Add-darwin-lsandbox-in-meson.patch ./patches/2_24/0003-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_24/0004-local-derivation-goal-Refactor.patch ./patches/2_24/0005-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }).override (lib.optionalAttrs (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) { # Fix the following error with the default x86_64-darwin SDK: # Loading @@ -234,6 +277,14 @@ in lib.makeExtensible (self: ({ rev = "ca3fc1693b309ab6b8b0c09408a08d0055bf0363"; hash = "sha256-Hp7dkx7zfB9a4l5QusXUob0b1T2qdZ23LFo5dcp3xrU="; }; patches = [ ./patches/git/0001-Fix-meson-build-on-darwin.patch ./patches/git/0002-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/git/0003-packaging-Add-darwin-lsandbox-in-meson.patch ./patches/git/0004-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/git/0005-local-derivation-goal-Refactor.patch ./patches/git/0006-local-derivation-goal-Move-builder-preparation-to-no.patch ]; self_attribute_name = "git"; }).override (lib.optionalAttrs (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) { # Fix the following error with the default x86_64-darwin SDK: Loading pkgs/tools/package-management/nix/patches/2_18/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch 0 → 100644 +315 −0 Original line number Diff line number Diff line From 3c4bc6929eb13cf648c54931a28797bb1c289052 Mon Sep 17 00:00:00 2001 From: Puck Meerburg <puck@puckipedia.com> Date: Fri, 1 Mar 2024 11:42:24 -0500 Subject: [PATCH 1/4] fix: Run all derivation builders inside the sandbox on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörg Thalheim <joerg@thalheim.io> --- configure.ac | 6 +- flake.nix | 1 + src/libstore/build/local-derivation-goal.cc | 221 ++++++++++---------- 3 files changed, 114 insertions(+), 114 deletions(-) diff --git a/configure.ac b/configure.ac index 4e50d0913..44852ad79 100644 --- a/configure.ac +++ b/configure.ac @@ -58,13 +58,17 @@ AC_CHECK_TOOL([AR], [ar]) AC_SYS_LARGEFILE -# Solaris-specific stuff. +# OS-specific stuff. AC_STRUCT_DIRENT_D_TYPE case "$host_os" in solaris*) # Solaris requires -lsocket -lnsl for network functions LDFLAGS="-lsocket -lnsl $LDFLAGS" ;; + darwin*) + # Need to link to libsandbox. + LDFLAGS="-lsandbox $LDFLAGS" + ;; esac diff --git a/flake.nix b/flake.nix index 6c9bef4d8..66ac1bfd8 100644 --- a/flake.nix +++ b/flake.nix @@ -173,6 +173,7 @@ boost lowdown-nix ] + ++ lib.optionals stdenv.isDarwin [darwin.apple_sdk.libs.sandbox] ++ lib.optionals stdenv.isLinux [(libseccomp.overrideAttrs (_: rec { version = "2.5.5"; src = fetchurl { diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 4d690beaf..fb83cfdc7 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -53,6 +53,10 @@ #if __APPLE__ #include <spawn.h> #include <sys/sysctl.h> +#include <sandbox.h> + +/* This definition is undocumented but depended upon by all major browsers. */ +extern "C" int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); #endif #include <pwd.h> @@ -2034,141 +2038,132 @@ void LocalDerivationGoal::runChild() std::string builder = "invalid"; - if (drv->isBuiltin()) { - ; - } #if __APPLE__ - else { - /* This has to appear before import statements. */ - std::string sandboxProfile = "(version 1)\n"; - - if (useChroot) { - - /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */ - PathSet ancestry; - - /* We build the ancestry before adding all inputPaths to the store because we know they'll - all have the same parents (the store), and there might be lots of inputs. This isn't - particularly efficient... I doubt it'll be a bottleneck in practice */ - for (auto & i : dirsInChroot) { - Path cur = i.first; - while (cur.compare("/") != 0) { - cur = dirOf(cur); - ancestry.insert(cur); - } - } + /* This has to appear before import statements. */ + std::string sandboxProfile = "(version 1)\n"; - /* And we want the store in there regardless of how empty dirsInChroot. We include the innermost - path component this time, since it's typically /nix/store and we care about that. */ - Path cur = worker.store.storeDir; + if (useChroot) { + + /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */ + PathSet ancestry; + + /* We build the ancestry before adding all inputPaths to the store because we know they'll + all have the same parents (the store), and there might be lots of inputs. This isn't + particularly efficient... I doubt it'll be a bottleneck in practice */ + for (auto & i : dirsInChroot) { + Path cur = i.first; while (cur.compare("/") != 0) { - ancestry.insert(cur); cur = dirOf(cur); + ancestry.insert(cur); } + } - /* Add all our input paths to the chroot */ - for (auto & i : inputPaths) { - auto p = worker.store.printStorePath(i); - dirsInChroot[p] = p; - } - - /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ - if (settings.darwinLogSandboxViolations) { - sandboxProfile += "(deny default)\n"; - } else { - sandboxProfile += "(deny default (with no-log))\n"; - } + /* And we want the store in there regardless of how empty dirsInChroot. We include the innermost + path component this time, since it's typically /nix/store and we care about that. */ + Path cur = worker.store.storeDir; + while (cur.compare("/") != 0) { + ancestry.insert(cur); + cur = dirOf(cur); + } - sandboxProfile += - #include "sandbox-defaults.sb" - ; + /* Add all our input paths to the chroot */ + for (auto & i : inputPaths) { + auto p = worker.store.printStorePath(i); + dirsInChroot[p] = p; + } - if (!derivationType->isSandboxed()) - sandboxProfile += - #include "sandbox-network.sb" - ; - - /* Add the output paths we'll use at build-time to the chroot */ - sandboxProfile += "(allow file-read* file-write* process-exec\n"; - for (auto & [_, path] : scratchOutputs) - sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(path)); - - sandboxProfile += ")\n"; - - /* Our inputs (transitive dependencies and any impurities computed above) - - without file-write* allowed, access() incorrectly returns EPERM - */ - sandboxProfile += "(allow file-read* file-write* process-exec\n"; - for (auto & i : dirsInChroot) { - if (i.first != i.second.source) - throw Error( - "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin", - i.first, i.second.source); - - std::string path = i.first; - struct stat st; - if (lstat(path.c_str(), &st)) { - if (i.second.optional && errno == ENOENT) - continue; - throw SysError("getting attributes of path '%s", path); - } - if (S_ISDIR(st.st_mode)) - sandboxProfile += fmt("\t(subpath \"%s\")\n", path); - else - sandboxProfile += fmt("\t(literal \"%s\")\n", path); - } - sandboxProfile += ")\n"; + /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ + if (settings.darwinLogSandboxViolations) { + sandboxProfile += "(deny default)\n"; + } else { + sandboxProfile += "(deny default (with no-log))\n"; + } - /* Allow file-read* on full directory hierarchy to self. Allows realpath() */ - sandboxProfile += "(allow file-read*\n"; - for (auto & i : ancestry) { - sandboxProfile += fmt("\t(literal \"%s\")\n", i); - } - sandboxProfile += ")\n"; + sandboxProfile += + #include "sandbox-defaults.sb" + ; - sandboxProfile += additionalSandboxProfile; - } else + if (!derivationType->isSandboxed()) sandboxProfile += - #include "sandbox-minimal.sb" + #include "sandbox-network.sb" ; - debug("Generated sandbox profile:"); - debug(sandboxProfile); + /* Add the output paths we'll use at build-time to the chroot */ + sandboxProfile += "(allow file-read* file-write* process-exec\n"; + for (auto & [_, path] : scratchOutputs) + sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(path)); - Path sandboxFile = tmpDir + "/.sandbox.sb"; + sandboxProfile += ")\n"; - writeFile(sandboxFile, sandboxProfile); + /* Our inputs (transitive dependencies and any impurities computed above) - bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking"); + without file-write* allowed, access() incorrectly returns EPERM + */ + sandboxProfile += "(allow file-read* file-write* process-exec\n"; + for (auto & i : dirsInChroot) { + if (i.first != i.second.source) + throw Error( + "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin", + i.first, i.second.source); - /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms - to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */ - Path globalTmpDir = canonPath(defaultTempDir(), true); + std::string path = i.first; + struct stat st; + if (lstat(path.c_str(), &st)) { + if (i.second.optional && errno == ENOENT) + continue; + throw SysError("getting attributes of path '%s", path); + } + if (S_ISDIR(st.st_mode)) + sandboxProfile += fmt("\t(subpath \"%s\")\n", path); + else + sandboxProfile += fmt("\t(literal \"%s\")\n", path); + } + sandboxProfile += ")\n"; - /* They don't like trailing slashes on subpath directives */ - while (!globalTmpDir.empty() && globalTmpDir.back() == '/') - globalTmpDir.pop_back(); + /* Allow file-read* on full directory hierarchy to self. Allows realpath() */ + sandboxProfile += "(allow file-read*\n"; + for (auto & i : ancestry) { + sandboxProfile += fmt("\t(literal \"%s\")\n", i); + } + sandboxProfile += ")\n"; - if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { - builder = "/usr/bin/sandbox-exec"; - args.push_back("sandbox-exec"); - args.push_back("-f"); - args.push_back(sandboxFile); - args.push_back("-D"); - args.push_back("_GLOBAL_TMP_DIR=" + globalTmpDir); - if (allowLocalNetworking) { - args.push_back("-D"); - args.push_back(std::string("_ALLOW_LOCAL_NETWORKING=1")); - } - args.push_back(drv->builder); - } else { - builder = drv->builder; - args.push_back(std::string(baseNameOf(drv->builder))); + sandboxProfile += additionalSandboxProfile; + } else + sandboxProfile += + #include "sandbox-minimal.sb" + ; + + debug("Generated sandbox profile:"); + debug(sandboxProfile); + + bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking"); + + /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms + to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */ + Path globalTmpDir = canonPath(defaultTempDir(), true); + + /* They don't like trailing slashes on subpath directives */ + while (!globalTmpDir.empty() && globalTmpDir.back() == '/') + globalTmpDir.pop_back(); + + if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { + Strings sandboxArgs; + sandboxArgs.push_back("_GLOBAL_TMP_DIR"); + sandboxArgs.push_back(globalTmpDir); + if (allowLocalNetworking) { + sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING"); + sandboxArgs.push_back("1"); + } + if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), NULL)) { + writeFull(STDERR_FILENO, "failed to configure sandbox\n"); + _exit(1); } } + + builder = drv->builder; + args.push_back(std::string(baseNameOf(drv->builder))); #else - else { + if (!drv->isBuiltin()) { builder = drv->builder; args.push_back(std::string(baseNameOf(drv->builder))); } -- 2.46.1 pkgs/tools/package-management/nix/patches/2_18/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch 0 → 100644 +34 −0 Original line number Diff line number Diff line From 4ac099d6ab4b6851aeb8b7a1e37f5794716d5138 Mon Sep 17 00:00:00 2001 From: Robert Hensing <robert@roberthensing.nl> Date: Thu, 3 Oct 2024 12:44:12 +0200 Subject: [PATCH 2/4] local-derivation-goal: Print sandbox error detail on darwin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Théophane Hufschmitt <theophane.hufschmitt@tweag.io> Signed-off-by: Jörg Thalheim <joerg@thalheim.io> --- src/libstore/build/local-derivation-goal.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index fb83cfdc7..d41d1c1e5 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -2154,8 +2154,9 @@ void LocalDerivationGoal::runChild() sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING"); sandboxArgs.push_back("1"); } - if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), NULL)) { - writeFull(STDERR_FILENO, "failed to configure sandbox\n"); + char * sandbox_errbuf = nullptr; + if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), &sandbox_errbuf)) { + writeFull(STDERR_FILENO, fmt("failed to configure sandbox: %s\n", sandbox_errbuf ? sandbox_errbuf : "(null)")); _exit(1); } } -- 2.46.1 pkgs/tools/package-management/nix/patches/2_18/0003-local-derivation-goal-Refactor.patch 0 → 100644 +41 −0 Original line number Diff line number Diff line From 6fe3a5e26def808b99856099d74aa3017ecf6d9d Mon Sep 17 00:00:00 2001 From: Robert Hensing <robert@roberthensing.nl> Date: Thu, 3 Oct 2024 12:50:27 +0200 Subject: [PATCH 3/4] local-derivation-goal: Refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This works because the `builder` and `args` variables are only used in the non-builtin code path. Co-Authored-By: Théophane Hufschmitt <theophane.hufschmitt@tweag.io> Signed-off-by: Jörg Thalheim <joerg@thalheim.io> --- src/libstore/build/local-derivation-goal.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index d41d1c1e5..faecc403b 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -2160,15 +2160,12 @@ void LocalDerivationGoal::runChild() _exit(1); } } +#endif - builder = drv->builder; - args.push_back(std::string(baseNameOf(drv->builder))); -#else if (!drv->isBuiltin()) { builder = drv->builder; args.push_back(std::string(baseNameOf(drv->builder))); } -#endif for (auto & i : drv->args) args.push_back(rewriteStrings(i, inputRewrites)); -- 2.46.1 Loading
pkgs/tools/package-management/nix/common.nix +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ let atLeast210 = lib.versionAtLeast version "2.10pre"; atLeast213 = lib.versionAtLeast version "2.13pre"; atLeast214 = lib.versionAtLeast version "2.14pre"; atLeast218 = lib.versionAtLeast version "2.18pre"; atLeast219 = lib.versionAtLeast version "2.19pre"; atLeast220 = lib.versionAtLeast version "2.20pre"; atLeast221 = lib.versionAtLeast version "2.21pre"; Loading @@ -42,6 +43,7 @@ in , callPackage , coreutils , curl , darwin , docbook_xsl_ns , docbook5 , editline Loading Loading @@ -158,6 +160,8 @@ self = stdenv.mkDerivation { libseccomp ] ++ lib.optionals withAWS [ aws-sdk-cpp ] ++ lib.optional (atLeast218 && stdenv.hostPlatform.isDarwin) [ darwin.apple_sdk.libs.sandbox ]; Loading
pkgs/tools/package-management/nix/default.nix +51 −0 Original line number Diff line number Diff line Loading @@ -178,42 +178,85 @@ in lib.makeExtensible (self: ({ version = "2.18.8"; hash = "sha256-0rHRifdjzzxMh/im8pRx6XoY62irDTDUes+Pn0CR65I="; self_attribute_name = "nix_2_18"; patches = [ ./patches/2_18/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_18/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_18/0003-local-derivation-goal-Refactor.patch ./patches/2_18/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_19 = common { version = "2.19.6"; hash = "sha256-XT5xiwOLgXf+TdyOjbJVOl992wu9mBO25WXHoyli/Tk="; self_attribute_name = "nix_2_19"; patches = [ ./patches/2_19/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_19/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_19/0003-local-derivation-goal-Refactor.patch ./patches/2_19/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_20 = common { version = "2.20.8"; hash = "sha256-M2tkMtjKi8LDdNLsKi3IvD8oY/i3rtarjMpvhybS3WY="; self_attribute_name = "nix_2_20"; patches = [ ./patches/2_20/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_20/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_20/0003-local-derivation-goal-Refactor.patch ./patches/2_20/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_21 = common { version = "2.21.4"; hash = "sha256-c6nVZ0pSrfhFX3eVKqayS+ioqyAGp3zG9ZPO5rkXFRQ="; self_attribute_name = "nix_2_21"; patches = [ ./patches/2_21/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_21/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_21/0003-local-derivation-goal-Refactor.patch ./patches/2_21/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_22 = common { version = "2.22.3"; hash = "sha256-l04csH5rTWsK7eXPWVxJBUVRPMZXllFoSkYFTq/i8WU="; self_attribute_name = "nix_2_22"; patches = [ ./patches/2_22/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_22/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_22/0003-local-derivation-goal-Refactor.patch ./patches/2_22/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_23 = common { version = "2.23.3"; hash = "sha256-lAoLGVIhRFrfgv7wcyduEkyc83QKrtsfsq4of+WrBeg="; self_attribute_name = "nix_2_23"; patches = [ ./patches/2_23/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_23/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_23/0003-local-derivation-goal-Refactor.patch ./patches/2_23/0004-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }; nix_2_24 = (common { version = "2.24.9"; hash = "sha256-OwJByTdCz1t91ysBqynK+ifszkoIGEXUn6HE2t82+c8="; self_attribute_name = "nix_2_24"; patches = [ ./patches/2_24/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/2_24/0002-packaging-Add-darwin-lsandbox-in-meson.patch ./patches/2_24/0003-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/2_24/0004-local-derivation-goal-Refactor.patch ./patches/2_24/0005-local-derivation-goal-Move-builder-preparation-to-no.patch ]; }).override (lib.optionalAttrs (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) { # Fix the following error with the default x86_64-darwin SDK: # Loading @@ -234,6 +277,14 @@ in lib.makeExtensible (self: ({ rev = "ca3fc1693b309ab6b8b0c09408a08d0055bf0363"; hash = "sha256-Hp7dkx7zfB9a4l5QusXUob0b1T2qdZ23LFo5dcp3xrU="; }; patches = [ ./patches/git/0001-Fix-meson-build-on-darwin.patch ./patches/git/0002-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch ./patches/git/0003-packaging-Add-darwin-lsandbox-in-meson.patch ./patches/git/0004-local-derivation-goal-Print-sandbox-error-detail-on-.patch ./patches/git/0005-local-derivation-goal-Refactor.patch ./patches/git/0006-local-derivation-goal-Move-builder-preparation-to-no.patch ]; self_attribute_name = "git"; }).override (lib.optionalAttrs (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) { # Fix the following error with the default x86_64-darwin SDK: Loading
pkgs/tools/package-management/nix/patches/2_18/0001-fix-Run-all-derivation-builders-inside-the-sandbox-o.patch 0 → 100644 +315 −0 Original line number Diff line number Diff line From 3c4bc6929eb13cf648c54931a28797bb1c289052 Mon Sep 17 00:00:00 2001 From: Puck Meerburg <puck@puckipedia.com> Date: Fri, 1 Mar 2024 11:42:24 -0500 Subject: [PATCH 1/4] fix: Run all derivation builders inside the sandbox on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörg Thalheim <joerg@thalheim.io> --- configure.ac | 6 +- flake.nix | 1 + src/libstore/build/local-derivation-goal.cc | 221 ++++++++++---------- 3 files changed, 114 insertions(+), 114 deletions(-) diff --git a/configure.ac b/configure.ac index 4e50d0913..44852ad79 100644 --- a/configure.ac +++ b/configure.ac @@ -58,13 +58,17 @@ AC_CHECK_TOOL([AR], [ar]) AC_SYS_LARGEFILE -# Solaris-specific stuff. +# OS-specific stuff. AC_STRUCT_DIRENT_D_TYPE case "$host_os" in solaris*) # Solaris requires -lsocket -lnsl for network functions LDFLAGS="-lsocket -lnsl $LDFLAGS" ;; + darwin*) + # Need to link to libsandbox. + LDFLAGS="-lsandbox $LDFLAGS" + ;; esac diff --git a/flake.nix b/flake.nix index 6c9bef4d8..66ac1bfd8 100644 --- a/flake.nix +++ b/flake.nix @@ -173,6 +173,7 @@ boost lowdown-nix ] + ++ lib.optionals stdenv.isDarwin [darwin.apple_sdk.libs.sandbox] ++ lib.optionals stdenv.isLinux [(libseccomp.overrideAttrs (_: rec { version = "2.5.5"; src = fetchurl { diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 4d690beaf..fb83cfdc7 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -53,6 +53,10 @@ #if __APPLE__ #include <spawn.h> #include <sys/sysctl.h> +#include <sandbox.h> + +/* This definition is undocumented but depended upon by all major browsers. */ +extern "C" int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); #endif #include <pwd.h> @@ -2034,141 +2038,132 @@ void LocalDerivationGoal::runChild() std::string builder = "invalid"; - if (drv->isBuiltin()) { - ; - } #if __APPLE__ - else { - /* This has to appear before import statements. */ - std::string sandboxProfile = "(version 1)\n"; - - if (useChroot) { - - /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */ - PathSet ancestry; - - /* We build the ancestry before adding all inputPaths to the store because we know they'll - all have the same parents (the store), and there might be lots of inputs. This isn't - particularly efficient... I doubt it'll be a bottleneck in practice */ - for (auto & i : dirsInChroot) { - Path cur = i.first; - while (cur.compare("/") != 0) { - cur = dirOf(cur); - ancestry.insert(cur); - } - } + /* This has to appear before import statements. */ + std::string sandboxProfile = "(version 1)\n"; - /* And we want the store in there regardless of how empty dirsInChroot. We include the innermost - path component this time, since it's typically /nix/store and we care about that. */ - Path cur = worker.store.storeDir; + if (useChroot) { + + /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */ + PathSet ancestry; + + /* We build the ancestry before adding all inputPaths to the store because we know they'll + all have the same parents (the store), and there might be lots of inputs. This isn't + particularly efficient... I doubt it'll be a bottleneck in practice */ + for (auto & i : dirsInChroot) { + Path cur = i.first; while (cur.compare("/") != 0) { - ancestry.insert(cur); cur = dirOf(cur); + ancestry.insert(cur); } + } - /* Add all our input paths to the chroot */ - for (auto & i : inputPaths) { - auto p = worker.store.printStorePath(i); - dirsInChroot[p] = p; - } - - /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ - if (settings.darwinLogSandboxViolations) { - sandboxProfile += "(deny default)\n"; - } else { - sandboxProfile += "(deny default (with no-log))\n"; - } + /* And we want the store in there regardless of how empty dirsInChroot. We include the innermost + path component this time, since it's typically /nix/store and we care about that. */ + Path cur = worker.store.storeDir; + while (cur.compare("/") != 0) { + ancestry.insert(cur); + cur = dirOf(cur); + } - sandboxProfile += - #include "sandbox-defaults.sb" - ; + /* Add all our input paths to the chroot */ + for (auto & i : inputPaths) { + auto p = worker.store.printStorePath(i); + dirsInChroot[p] = p; + } - if (!derivationType->isSandboxed()) - sandboxProfile += - #include "sandbox-network.sb" - ; - - /* Add the output paths we'll use at build-time to the chroot */ - sandboxProfile += "(allow file-read* file-write* process-exec\n"; - for (auto & [_, path] : scratchOutputs) - sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(path)); - - sandboxProfile += ")\n"; - - /* Our inputs (transitive dependencies and any impurities computed above) - - without file-write* allowed, access() incorrectly returns EPERM - */ - sandboxProfile += "(allow file-read* file-write* process-exec\n"; - for (auto & i : dirsInChroot) { - if (i.first != i.second.source) - throw Error( - "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin", - i.first, i.second.source); - - std::string path = i.first; - struct stat st; - if (lstat(path.c_str(), &st)) { - if (i.second.optional && errno == ENOENT) - continue; - throw SysError("getting attributes of path '%s", path); - } - if (S_ISDIR(st.st_mode)) - sandboxProfile += fmt("\t(subpath \"%s\")\n", path); - else - sandboxProfile += fmt("\t(literal \"%s\")\n", path); - } - sandboxProfile += ")\n"; + /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */ + if (settings.darwinLogSandboxViolations) { + sandboxProfile += "(deny default)\n"; + } else { + sandboxProfile += "(deny default (with no-log))\n"; + } - /* Allow file-read* on full directory hierarchy to self. Allows realpath() */ - sandboxProfile += "(allow file-read*\n"; - for (auto & i : ancestry) { - sandboxProfile += fmt("\t(literal \"%s\")\n", i); - } - sandboxProfile += ")\n"; + sandboxProfile += + #include "sandbox-defaults.sb" + ; - sandboxProfile += additionalSandboxProfile; - } else + if (!derivationType->isSandboxed()) sandboxProfile += - #include "sandbox-minimal.sb" + #include "sandbox-network.sb" ; - debug("Generated sandbox profile:"); - debug(sandboxProfile); + /* Add the output paths we'll use at build-time to the chroot */ + sandboxProfile += "(allow file-read* file-write* process-exec\n"; + for (auto & [_, path] : scratchOutputs) + sandboxProfile += fmt("\t(subpath \"%s\")\n", worker.store.printStorePath(path)); - Path sandboxFile = tmpDir + "/.sandbox.sb"; + sandboxProfile += ")\n"; - writeFile(sandboxFile, sandboxProfile); + /* Our inputs (transitive dependencies and any impurities computed above) - bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking"); + without file-write* allowed, access() incorrectly returns EPERM + */ + sandboxProfile += "(allow file-read* file-write* process-exec\n"; + for (auto & i : dirsInChroot) { + if (i.first != i.second.source) + throw Error( + "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin", + i.first, i.second.source); - /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms - to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */ - Path globalTmpDir = canonPath(defaultTempDir(), true); + std::string path = i.first; + struct stat st; + if (lstat(path.c_str(), &st)) { + if (i.second.optional && errno == ENOENT) + continue; + throw SysError("getting attributes of path '%s", path); + } + if (S_ISDIR(st.st_mode)) + sandboxProfile += fmt("\t(subpath \"%s\")\n", path); + else + sandboxProfile += fmt("\t(literal \"%s\")\n", path); + } + sandboxProfile += ")\n"; - /* They don't like trailing slashes on subpath directives */ - while (!globalTmpDir.empty() && globalTmpDir.back() == '/') - globalTmpDir.pop_back(); + /* Allow file-read* on full directory hierarchy to self. Allows realpath() */ + sandboxProfile += "(allow file-read*\n"; + for (auto & i : ancestry) { + sandboxProfile += fmt("\t(literal \"%s\")\n", i); + } + sandboxProfile += ")\n"; - if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { - builder = "/usr/bin/sandbox-exec"; - args.push_back("sandbox-exec"); - args.push_back("-f"); - args.push_back(sandboxFile); - args.push_back("-D"); - args.push_back("_GLOBAL_TMP_DIR=" + globalTmpDir); - if (allowLocalNetworking) { - args.push_back("-D"); - args.push_back(std::string("_ALLOW_LOCAL_NETWORKING=1")); - } - args.push_back(drv->builder); - } else { - builder = drv->builder; - args.push_back(std::string(baseNameOf(drv->builder))); + sandboxProfile += additionalSandboxProfile; + } else + sandboxProfile += + #include "sandbox-minimal.sb" + ; + + debug("Generated sandbox profile:"); + debug(sandboxProfile); + + bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking"); + + /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms + to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */ + Path globalTmpDir = canonPath(defaultTempDir(), true); + + /* They don't like trailing slashes on subpath directives */ + while (!globalTmpDir.empty() && globalTmpDir.back() == '/') + globalTmpDir.pop_back(); + + if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { + Strings sandboxArgs; + sandboxArgs.push_back("_GLOBAL_TMP_DIR"); + sandboxArgs.push_back(globalTmpDir); + if (allowLocalNetworking) { + sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING"); + sandboxArgs.push_back("1"); + } + if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), NULL)) { + writeFull(STDERR_FILENO, "failed to configure sandbox\n"); + _exit(1); } } + + builder = drv->builder; + args.push_back(std::string(baseNameOf(drv->builder))); #else - else { + if (!drv->isBuiltin()) { builder = drv->builder; args.push_back(std::string(baseNameOf(drv->builder))); } -- 2.46.1
pkgs/tools/package-management/nix/patches/2_18/0002-local-derivation-goal-Print-sandbox-error-detail-on-.patch 0 → 100644 +34 −0 Original line number Diff line number Diff line From 4ac099d6ab4b6851aeb8b7a1e37f5794716d5138 Mon Sep 17 00:00:00 2001 From: Robert Hensing <robert@roberthensing.nl> Date: Thu, 3 Oct 2024 12:44:12 +0200 Subject: [PATCH 2/4] local-derivation-goal: Print sandbox error detail on darwin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Théophane Hufschmitt <theophane.hufschmitt@tweag.io> Signed-off-by: Jörg Thalheim <joerg@thalheim.io> --- src/libstore/build/local-derivation-goal.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index fb83cfdc7..d41d1c1e5 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -2154,8 +2154,9 @@ void LocalDerivationGoal::runChild() sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING"); sandboxArgs.push_back("1"); } - if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), NULL)) { - writeFull(STDERR_FILENO, "failed to configure sandbox\n"); + char * sandbox_errbuf = nullptr; + if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), &sandbox_errbuf)) { + writeFull(STDERR_FILENO, fmt("failed to configure sandbox: %s\n", sandbox_errbuf ? sandbox_errbuf : "(null)")); _exit(1); } } -- 2.46.1
pkgs/tools/package-management/nix/patches/2_18/0003-local-derivation-goal-Refactor.patch 0 → 100644 +41 −0 Original line number Diff line number Diff line From 6fe3a5e26def808b99856099d74aa3017ecf6d9d Mon Sep 17 00:00:00 2001 From: Robert Hensing <robert@roberthensing.nl> Date: Thu, 3 Oct 2024 12:50:27 +0200 Subject: [PATCH 3/4] local-derivation-goal: Refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This works because the `builder` and `args` variables are only used in the non-builtin code path. Co-Authored-By: Théophane Hufschmitt <theophane.hufschmitt@tweag.io> Signed-off-by: Jörg Thalheim <joerg@thalheim.io> --- src/libstore/build/local-derivation-goal.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index d41d1c1e5..faecc403b 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -2160,15 +2160,12 @@ void LocalDerivationGoal::runChild() _exit(1); } } +#endif - builder = drv->builder; - args.push_back(std::string(baseNameOf(drv->builder))); -#else if (!drv->isBuiltin()) { builder = drv->builder; args.push_back(std::string(baseNameOf(drv->builder))); } -#endif for (auto & i : drv->args) args.push_back(rewriteStrings(i, inputRewrites)); -- 2.46.1