From 668ac3ea2c4c7390761dfbc5738c2aa85fda9751 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 20 Mar 2018 17:28:09 +0100 Subject: [PATCH] Make a builtin builder This avoids sandbox annoyances. --- .gitignore | 6 - Makefile | 1 - corepkgs/buildenv.nix | 23 +--- src/buildenv/local.mk | 9 -- src/libstore/build.cc | 2 + src/libstore/builtins.hh | 2 + .../builtins}/buildenv.cc | 120 +++++++++--------- 7 files changed, 69 insertions(+), 94 deletions(-) delete mode 100644 src/buildenv/local.mk rename src/{buildenv => libstore/builtins}/buildenv.cc (64%) diff --git a/.gitignore b/.gitignore index 0a959937..0f2f3dde 100644 --- a/.gitignore +++ b/.gitignore @@ -13,9 +13,6 @@ perl/Makefile.config /corepkgs/config.nix -# /corepkgs/buildenv/ -/corepkgs/buildenv/builder.pl - # /corepkgs/channels/ /corepkgs/channels/unpack.sh @@ -72,9 +69,6 @@ perl/Makefile.config # /src/nix-channel/ /src/nix-channel/nix-channel -# /src/buildenv/ -/src/buildenv/buildenv - # /src/nix-build/ /src/nix-build/nix-build diff --git a/Makefile b/Makefile index c4760373..dbe864ec 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,6 @@ makefiles = \ src/nix-collect-garbage/local.mk \ src/nix-copy-closure/local.mk \ src/nix-prefetch-url/local.mk \ - src/buildenv/local.mk \ src/resolve-system-dependencies/local.mk \ src/nix-channel/local.mk \ src/nix-build/local.mk \ diff --git a/corepkgs/buildenv.nix b/corepkgs/buildenv.nix index 5e7b40ea..0bac4c44 100644 --- a/corepkgs/buildenv.nix +++ b/corepkgs/buildenv.nix @@ -1,11 +1,9 @@ -with import ; - { derivations, manifest }: derivation { name = "user-environment"; - system = builtins.currentSystem; - builder = nixLibexecDir + "/nix/buildenv"; + system = "builtin"; + builder = "builtin:buildenv"; inherit manifest; @@ -24,21 +22,4 @@ derivation { # Also don't bother substituting. allowSubstitutes = false; - - __sandboxProfile = '' - (allow sysctl-read) - (allow file-read* - (literal "/usr/lib/libSystem.dylib") - (literal "/usr/lib/libSystem.B.dylib") - (literal "/usr/lib/libobjc.A.dylib") - (literal "/usr/lib/libobjc.dylib") - (literal "/usr/lib/libauto.dylib") - (literal "/usr/lib/libc++abi.dylib") - (literal "/usr/lib/libc++.1.dylib") - (literal "/usr/lib/libDiagnosticMessagesClient.dylib") - (subpath "/usr/lib/system") - (subpath "/dev")) - ''; - - inherit chrootDeps; } diff --git a/src/buildenv/local.mk b/src/buildenv/local.mk deleted file mode 100644 index 17ec13b2..00000000 --- a/src/buildenv/local.mk +++ /dev/null @@ -1,9 +0,0 @@ -programs += buildenv - -buildenv_DIR := $(d) - -buildenv_INSTALL_DIR := $(libexecdir)/nix - -buildenv_LIBS = libmain libstore libutil libformat - -buildenv_SOURCES := $(d)/buildenv.cc diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 5c548755..082cd7db 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -2949,6 +2949,8 @@ void DerivationGoal::runChild() if (drv->builder == "builtin:fetchurl") builtinFetchurl(drv2, netrcData); + else if (drv->builder == "builtin:buildenv") + builtinBuildenv(drv2); else throw Error(format("unsupported builtin function '%1%'") % string(drv->builder, 8)); _exit(0); diff --git a/src/libstore/builtins.hh b/src/libstore/builtins.hh index 0cc6ba31..0d2da873 100644 --- a/src/libstore/builtins.hh +++ b/src/libstore/builtins.hh @@ -4,6 +4,8 @@ namespace nix { +// TODO: make pluggable. void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData); +void builtinBuildenv(const BasicDerivation & drv); } diff --git a/src/buildenv/buildenv.cc b/src/libstore/builtins/buildenv.cc similarity index 64% rename from src/buildenv/buildenv.cc rename to src/libstore/builtins/buildenv.cc index 2afad913..938d02c3 100644 --- a/src/buildenv/buildenv.cc +++ b/src/libstore/builtins/buildenv.cc @@ -1,14 +1,15 @@ -#include "shared.hh" +#include "builtins.hh" + #include #include #include #include -using namespace nix; +namespace nix { typedef std::map Priorities; -static bool isDirectory (const Path & path) +static bool isDirectory(const Path & path) { struct stat st; if (stat(path.c_str(), &st) == -1) @@ -16,9 +17,11 @@ static bool isDirectory (const Path & path) return S_ISDIR(st.st_mode); } -static auto priorities = Priorities{}; +// FIXME: change into local variables. -static auto symlinks = 0; +static Priorities priorities; + +static unsigned long symlinks; /* For each activated package, create symlinks */ static void createLinks(const Path & srcDir, const Path & dstDir, int priority) @@ -95,10 +98,10 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority) typedef std::set FileProp; -static auto done = FileProp{}; -static auto postponed = FileProp{}; +static FileProp done; +static FileProp postponed = FileProp{}; -static auto out = string{}; +static Path out; static void addPkg(const Path & pkgDir, int priority) { @@ -107,7 +110,7 @@ static void addPkg(const Path & pkgDir, int priority) done.insert(pkgDir); createLinks(pkgDir, out, priority); auto propagatedFN = pkgDir + "/nix-support/propagated-user-env-packages"; - auto propagated = string{}; + std::string propagated; { AutoCloseFD fd = open(propagatedFN.c_str(), O_RDONLY | O_CLOEXEC); if (!fd) { @@ -126,62 +129,65 @@ struct Package { Path path; bool active; int priority; - Package(Path path, bool active, int priority) : path{std::move(path)}, active{active}, priority{priority} {} + Package(Path path, bool active, int priority) : path{path}, active{active}, priority{priority} {} }; typedef std::vector Packages; -int main(int argc, char ** argv) +void builtinBuildenv(const BasicDerivation & drv) { - return handleExceptions(argv[0], [&]() { - initNix(); - out = getEnv("out"); - if (mkdir(out.c_str(), 0755) == -1) - throw SysError(format("creating %1%") % out); + auto getAttr = [&](const string & name) { + auto i = drv.env.find(name); + if (i == drv.env.end()) throw Error("attribute '%s' missing", name); + return i->second; + }; - /* Convert the stuff we get from the environment back into a coherent - * data type. - */ - auto pkgs = Packages{}; - auto derivations = tokenizeString(getEnv("derivations")); - while (!derivations.empty()) { - /* !!! We're trusting the caller to structure derivations env var correctly */ - auto active = derivations.front(); derivations.pop_front(); - auto priority = stoi(derivations.front()); derivations.pop_front(); - auto outputs = stoi(derivations.front()); derivations.pop_front(); - for (auto n = 0; n < outputs; n++) { - auto path = derivations.front(); derivations.pop_front(); - pkgs.emplace_back(path, active != "false", priority); - } + out = getAttr("out"); + createDirs(out); + + /* Convert the stuff we get from the environment back into a + * coherent data type. */ + Packages pkgs; + auto derivations = tokenizeString(getAttr("derivations")); + while (!derivations.empty()) { + /* !!! We're trusting the caller to structure derivations env var correctly */ + auto active = derivations.front(); derivations.pop_front(); + auto priority = stoi(derivations.front()); derivations.pop_front(); + auto outputs = stoi(derivations.front()); derivations.pop_front(); + for (auto n = 0; n < outputs; n++) { + auto path = derivations.front(); derivations.pop_front(); + pkgs.emplace_back(path, active != "false", priority); } + } - /* Symlink to the packages that have been installed explicitly by the - * user. Process in priority order to reduce unnecessary - * symlink/unlink steps. - */ - std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) { - return a.priority < b.priority || (a.priority == b.priority && a.path < b.path); - }); - for (const auto & pkg : pkgs) - if (pkg.active) - addPkg(pkg.path, pkg.priority); - - /* Symlink to the packages that have been "propagated" by packages - * installed by the user (i.e., package X declares that it wants Y - * installed as well). We do these later because they have a lower - * priority in case of collisions. - */ - auto priorityCounter = 1000; - while (!postponed.empty()) { - auto pkgDirs = postponed; - postponed = FileProp{}; - for (const auto & pkgDir : pkgDirs) - addPkg(pkgDir, priorityCounter++); - } - - std::cerr << "created " << symlinks << " symlinks in user environment\n"; - - createSymlink(getEnv("manifest"), out + "/manifest.nix"); + /* Symlink to the packages that have been installed explicitly by the + * user. Process in priority order to reduce unnecessary + * symlink/unlink steps. + */ + std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) { + return a.priority < b.priority || (a.priority == b.priority && a.path < b.path); }); + for (const auto & pkg : pkgs) + if (pkg.active) + addPkg(pkg.path, pkg.priority); + + /* Symlink to the packages that have been "propagated" by packages + * installed by the user (i.e., package X declares that it wants Y + * installed as well). We do these later because they have a lower + * priority in case of collisions. + */ + auto priorityCounter = 1000; + while (!postponed.empty()) { + auto pkgDirs = postponed; + postponed = FileProp{}; + for (const auto & pkgDir : pkgDirs) + addPkg(pkgDir, priorityCounter++); + } + + printError("created %d symlinks in user environment", symlinks); + + createSymlink(getAttr("manifest"), out + "/manifest.nix"); +} + }