forked from lix-project/lix
Run all derivation builders inside the sandbox on macOS
This replaces the external sandbox-exec call with direct calls into
libsandbox. This API is technically deprecated and is missing some
prototypes, but all major browsers depend on it, so it is unlikely to
materially change without warning.
This commit also ensures the netrc file is only written if the
derivation is in fact meant to be able to access the internet.
This change commits a sin of not actually actively declaring its
dependency on macOS's libsandbox.dylib; this is due to the dylib
cache in macOS making that explicit dependency unnecessary. In the
future this might become a problem, so this commit marks our sins.
Co-authored-by: Artemis Tosini <lix@artem.ist>
Co-authored-by: Lunaphied <lunaphied@lunaphied.me>
Change-Id: Ia302141a53ce7b0327c1aad86a117b6645fe1189
This commit is contained in:
parent
5ebf890af7
commit
fe5f11b92e
|
@ -52,6 +52,9 @@
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.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
|
#endif
|
||||||
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
@ -1711,7 +1714,7 @@ void LocalDerivationGoal::runChild()
|
||||||
(which may run under a different uid and/or in a sandbox). */
|
(which may run under a different uid and/or in a sandbox). */
|
||||||
std::string netrcData;
|
std::string netrcData;
|
||||||
try {
|
try {
|
||||||
if (drv->isBuiltin() && drv->builder == "builtin:fetchurl")
|
if (drv->isBuiltin() && drv->builder == "builtin:fetchurl" && !derivationType->isSandboxed())
|
||||||
netrcData = readFile(settings.netrcFile);
|
netrcData = readFile(settings.netrcFile);
|
||||||
} catch (SysError &) { }
|
} catch (SysError &) { }
|
||||||
|
|
||||||
|
@ -2005,11 +2008,7 @@ void LocalDerivationGoal::runChild()
|
||||||
|
|
||||||
std::string builder = "invalid";
|
std::string builder = "invalid";
|
||||||
|
|
||||||
if (drv->isBuiltin()) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
else {
|
|
||||||
/* This has to appear before import statements. */
|
/* This has to appear before import statements. */
|
||||||
std::string sandboxProfile = "(version 1)\n";
|
std::string sandboxProfile = "(version 1)\n";
|
||||||
|
|
||||||
|
@ -2078,13 +2077,13 @@ void LocalDerivationGoal::runChild()
|
||||||
i.first, i.second.source);
|
i.first, i.second.source);
|
||||||
|
|
||||||
std::string path = i.first;
|
std::string path = i.first;
|
||||||
auto optSt = maybeLstat(path.c_str());
|
struct stat st;
|
||||||
if (!optSt) {
|
if (lstat(path.c_str(), &st)) {
|
||||||
if (i.second.optional)
|
if (i.second.optional && errno == ENOENT)
|
||||||
continue;
|
continue;
|
||||||
throw SysError("getting attributes of required path '%s", path);
|
throw SysError("getting attributes of path '%s", path);
|
||||||
}
|
}
|
||||||
if (S_ISDIR(optSt->st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
sandboxProfile += fmt("\t(subpath \"%s\")\n", path);
|
sandboxProfile += fmt("\t(subpath \"%s\")\n", path);
|
||||||
else
|
else
|
||||||
sandboxProfile += fmt("\t(literal \"%s\")\n", path);
|
sandboxProfile += fmt("\t(literal \"%s\")\n", path);
|
||||||
|
@ -2107,10 +2106,6 @@ void LocalDerivationGoal::runChild()
|
||||||
debug("Generated sandbox profile:");
|
debug("Generated sandbox profile:");
|
||||||
debug(sandboxProfile);
|
debug(sandboxProfile);
|
||||||
|
|
||||||
Path sandboxFile = tmpDir + "/.sandbox.sb";
|
|
||||||
|
|
||||||
writeFile(sandboxFile, sandboxProfile);
|
|
||||||
|
|
||||||
bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking");
|
bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking");
|
||||||
|
|
||||||
/* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms
|
/* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms
|
||||||
|
@ -2121,24 +2116,23 @@ void LocalDerivationGoal::runChild()
|
||||||
if (globalTmpDir.back() == '/') globalTmpDir.pop_back();
|
if (globalTmpDir.back() == '/') globalTmpDir.pop_back();
|
||||||
|
|
||||||
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
|
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
|
||||||
builder = "/usr/bin/sandbox-exec";
|
Strings sandboxArgs;
|
||||||
args.push_back("sandbox-exec");
|
sandboxArgs.push_back("_GLOBAL_TMP_DIR");
|
||||||
args.push_back("-f");
|
sandboxArgs.push_back(globalTmpDir);
|
||||||
args.push_back(sandboxFile);
|
|
||||||
args.push_back("-D");
|
|
||||||
args.push_back("_GLOBAL_TMP_DIR=" + globalTmpDir);
|
|
||||||
if (allowLocalNetworking) {
|
if (allowLocalNetworking) {
|
||||||
args.push_back("-D");
|
sandboxArgs.push_back("_ALLOW_LOCAL_NETWORKING");
|
||||||
args.push_back(std::string("_ALLOW_LOCAL_NETWORKING=1"));
|
sandboxArgs.push_back("1");
|
||||||
}
|
}
|
||||||
args.push_back(drv->builder);
|
if (sandbox_init_with_parameters(sandboxProfile.c_str(), 0, stringsToCharPtrs(sandboxArgs).data(), NULL)) {
|
||||||
} else {
|
writeFull(STDERR_FILENO, "failed to configure sandbox\n");
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
builder = drv->builder;
|
builder = drv->builder;
|
||||||
args.push_back(std::string(baseNameOf(drv->builder)));
|
args.push_back(std::string(baseNameOf(drv->builder)));
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
else {
|
if (!drv->isBuiltin()) {
|
||||||
builder = drv->builder;
|
builder = drv->builder;
|
||||||
args.push_back(std::string(baseNameOf(drv->builder)));
|
args.push_back(std::string(baseNameOf(drv->builder)));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue