From 3d77ee8d94b3e8370bd85cd1430dd14dd475c3a7 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 2 Feb 2026 18:26:57 +0100 Subject: [PATCH] libstore: move macos sandbox config to capnp Change-Id: I0bc7c60329e0f24e15649c526386ba2466314b18 --- lix/libstore/build/request.capnp | 11 ++++++++++- lix/libstore/platform/darwin.cc | 31 ++++++++++++++++++++++--------- lix/libstore/platform/darwin.hh | 9 +++++---- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/lix/libstore/build/request.capnp b/lix/libstore/build/request.capnp index 16cc75fb9..5d1363514 100644 --- a/lix/libstore/build/request.capnp +++ b/lix/libstore/build/request.capnp @@ -37,6 +37,14 @@ struct Request { parentPid @3 :Int32; } + struct DarwinPlatform { + allowLocalNetworking @0 :Bool; + sandboxProfile @1 :Text; + platform @2 :Data; + tempDir @3 :Text; + globalTempDir @4 :Text; + } + builder @0 :Data; args @1 :List(Data); environment @2 :List(Data); @@ -44,7 +52,8 @@ struct Request { enableCoreDumps @4 :Bool; credentials @5 :Credentials; - platform :group { + platform :union { linux @6 :LinuxPlatform; + darwin @7 :DarwinPlatform; } } diff --git a/lix/libstore/platform/darwin.cc b/lix/libstore/platform/darwin.cc index ebd27c025..6491f72bc 100644 --- a/lix/libstore/platform/darwin.cc +++ b/lix/libstore/platform/darwin.cc @@ -255,10 +255,12 @@ try { co_return result::current_exception(); } -void DarwinLocalDerivationGoal::prepareSandbox() +void DarwinLocalDerivationGoal::fillBuilderConfig(build::Request::Builder request) { + auto config = request.getPlatform().getDarwin(); + /* This has to appear before import statements. */ - sandboxProfile = "(version 1)\n"; + std::string sandboxProfile = "(version 1)\n"; if (useChroot) { @@ -370,16 +372,22 @@ void DarwinLocalDerivationGoal::prepareSandbox() } debug("Generated sandbox profile: %1%", sandboxProfile); + + config.setAllowLocalNetworking(parsedDrv->getBoolAttr("__darwinAllowLocalNetworking")); + RPC_FILL(config, setSandboxProfile, sandboxProfile); + RPC_FILL(config, setPlatform, drv->platform); + RPC_FILL(config, setTempDir, tmpDir); + RPC_FILL(config, setGlobalTempDir, canonPath(defaultTempDir(), true)); } void DarwinLocalDerivationGoal::finishChildSetup(build::Request::Reader request) { - bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking"); + auto config = request.getPlatform().getDarwin(); /* 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 put their files, if needed. */ - Path globalTmpDir = canonPath(defaultTempDir(), true); + auto globalTmpDir = rpc::to(config.getGlobalTempDir()); /* They don't like trailing slashes on subpath directives */ if (globalTmpDir.back() == '/') { @@ -389,15 +397,16 @@ void DarwinLocalDerivationGoal::finishChildSetup(build::Request::Reader request) if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") { Strings sandboxArgs; sandboxArgs.push_back("_NIX_BUILD_TOP"); - sandboxArgs.push_back(tmpDir); + sandboxArgs.push_back(rpc::to(config.getTempDir())); sandboxArgs.push_back("_GLOBAL_TMP_DIR"); sandboxArgs.push_back(globalTmpDir); - if (allowLocalNetworking) { + if (config.getAllowLocalNetworking()) { sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING"); sandboxArgs.push_back("1"); } + // NOLINTNEXTLINE(lix-unsafe-c-calls): all of these are env names or paths if (sandbox_init_with_parameters( - sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), nullptr + config.getSandboxProfile().cStr(), 0, stringsToCharPtrs(sandboxArgs).data(), nullptr )) { writeFull(STDERR_FILENO, "failed to configure sandbox\n"); @@ -408,6 +417,8 @@ void DarwinLocalDerivationGoal::finishChildSetup(build::Request::Reader request) void DarwinLocalDerivationGoal::execBuilder(build::Request::Reader request) { + auto config = request.getPlatform().getDarwin(); + posix_spawnattr_t attrp; if (posix_spawnattr_init(&attrp)) @@ -416,14 +427,16 @@ void DarwinLocalDerivationGoal::execBuilder(build::Request::Reader request) if (posix_spawnattr_setflags(&attrp, POSIX_SPAWN_SETEXEC)) throw SysError("failed to initialize builder"); - if (drv->platform == "aarch64-darwin") { + const auto platform = rpc::to(config.getPlatform()); + + if (platform == "aarch64-darwin") { // Unset kern.curproc_arch_affinity so we can escape Rosetta int affinity = 0; sysctlbyname("kern.curproc_arch_affinity", nullptr, nullptr, &affinity, sizeof(affinity)); cpu_type_t cpu = CPU_TYPE_ARM64; posix_spawnattr_setbinpref_np(&attrp, 1, &cpu, nullptr); - } else if (drv->platform == "x86_64-darwin") { + } else if (platform == "x86_64-darwin") { cpu_type_t cpu = CPU_TYPE_X86_64; posix_spawnattr_setbinpref_np(&attrp, 1, &cpu, nullptr); } diff --git a/lix/libstore/platform/darwin.hh b/lix/libstore/platform/darwin.hh index 084d2452c..16a411ba7 100644 --- a/lix/libstore/platform/darwin.hh +++ b/lix/libstore/platform/darwin.hh @@ -37,12 +37,13 @@ public: using LocalDerivationGoal::LocalDerivationGoal; private: - std::string sandboxProfile; - /** - * Prepare the sandbox: generate the sandboxProfile + * no-op. sandbox profiles are generated in fillBuilderConfig, we only need + * to override this to signal that sandboxed builds are actually supported. */ - void prepareSandbox() override; + void prepareSandbox() override {} + + void fillBuilderConfig(build::Request::Builder config) override; void finishChildSetup(build::Request::Reader request) override;