diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/eval.cc | 15 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 1 | ||||
-rw-r--r-- | src/libexpr/tests/primops.cc | 2 | ||||
-rw-r--r-- | src/libstore/build/derivation-goal.cc | 1 | ||||
-rw-r--r-- | src/libstore/build/local-derivation-goal.cc | 31 | ||||
-rw-r--r-- | src/libstore/build/personality.cc | 44 | ||||
-rw-r--r-- | src/libstore/build/personality.hh | 11 | ||||
-rw-r--r-- | src/libstore/builtins/buildenv.cc | 2 | ||||
-rw-r--r-- | src/libstore/globals.hh | 5 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 2 | ||||
-rw-r--r-- | src/libstore/nar-info-disk-cache.cc | 42 | ||||
-rw-r--r-- | src/libutil/canon-path.hh | 2 | ||||
-rw-r--r-- | src/nix/develop.cc | 10 | ||||
-rw-r--r-- | src/nix/run.cc | 13 | ||||
-rw-r--r-- | src/nix/run.hh | 3 |
15 files changed, 121 insertions, 63 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 084ccbee2..ebf14b659 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -67,22 +67,19 @@ static char * dupString(const char * s) // When there's no need to write to the string, we can optimize away empty // string allocations. -// This function handles makeImmutableStringWithLen(null, 0) by returning the -// empty string. -static const char * makeImmutableStringWithLen(const char * s, size_t size) +// This function handles makeImmutableString(std::string_view()) by returning +// the empty string. +static const char * makeImmutableString(std::string_view s) { + const size_t size = s.size(); if (size == 0) return ""; auto t = allocString(size + 1); - memcpy(t, s, size); - t[size] = 0; + memcpy(t, s.data(), size); + t[size] = '\0'; return t; } -static inline const char * makeImmutableString(std::string_view s) { - return makeImmutableStringWithLen(s.data(), s.size()); -} - RootValue allocRootValue(Value * v) { diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 21666339b..346b2cb31 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -60,7 +60,6 @@ void copyContext(const Value & v, PathSet & context); typedef std::map<Path, StorePath> SrcToStore; -std::ostream & printValue(const EvalState & state, std::ostream & str, const Value & v); std::string printValue(const EvalState & state, const Value & v); std::ostream & operator << (std::ostream & os, const ValueType t); diff --git a/src/libexpr/tests/primops.cc b/src/libexpr/tests/primops.cc index 49fbc5e98..bcdc7086b 100644 --- a/src/libexpr/tests/primops.cc +++ b/src/libexpr/tests/primops.cc @@ -604,7 +604,7 @@ namespace nix { TEST_F(PrimOpTest, storeDir) { auto v = eval("builtins.storeDir"); - ASSERT_THAT(v, IsStringEq("/nix/store")); + ASSERT_THAT(v, IsStringEq(settings.nixStore)); } TEST_F(PrimOpTest, nixVersion) { diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index d3b995a4f..173058d1b 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -39,7 +39,6 @@ #include <sys/ioctl.h> #include <net/if.h> #include <netinet/ip.h> -#include <sys/personality.h> #include <sys/mman.h> #include <sched.h> #include <sys/param.h> diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index dccd096ec..9d869d513 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -15,6 +15,7 @@ #include "callback.hh" #include "json-utils.hh" #include "cgroup.hh" +#include "personality.hh" #include <regex> #include <queue> @@ -24,7 +25,6 @@ #include <termios.h> #include <unistd.h> #include <sys/mman.h> -#include <sys/utsname.h> #include <sys/resource.h> #include <sys/socket.h> @@ -37,7 +37,6 @@ #include <sys/ioctl.h> #include <net/if.h> #include <netinet/ip.h> -#include <sys/personality.h> #include <sys/mman.h> #include <sched.h> #include <sys/param.h> @@ -1964,33 +1963,7 @@ void LocalDerivationGoal::runChild() /* Close all other file descriptors. */ closeMostFDs({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}); -#if __linux__ - /* Change the personality to 32-bit if we're doing an - i686-linux build on an x86_64-linux machine. */ - struct utsname utsbuf; - uname(&utsbuf); - if ((drv->platform == "i686-linux" - && (settings.thisSystem == "x86_64-linux" - || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) - || drv->platform == "armv7l-linux" - || drv->platform == "armv6l-linux") - { - if (personality(PER_LINUX32) == -1) - throw SysError("cannot set 32-bit personality"); - } - - /* Impersonate a Linux 2.6 machine to get some determinism in - builds that depend on the kernel version. */ - if ((drv->platform == "i686-linux" || drv->platform == "x86_64-linux") && settings.impersonateLinux26) { - int cur = personality(0xffffffff); - if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */); - } - - /* Disable address space randomization for improved - determinism. */ - int cur = personality(0xffffffff); - if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE); -#endif + setPersonality(drv->platform); /* Disable core dumps by default. */ struct rlimit limit = { 0, RLIM_INFINITY }; diff --git a/src/libstore/build/personality.cc b/src/libstore/build/personality.cc new file mode 100644 index 000000000..4ad477869 --- /dev/null +++ b/src/libstore/build/personality.cc @@ -0,0 +1,44 @@ +#include "personality.hh" +#include "globals.hh" + +#if __linux__ +#include <sys/utsname.h> +#include <sys/personality.h> +#endif + +#include <cstring> + +namespace nix { + +void setPersonality(std::string_view system) +{ +#if __linux__ + /* Change the personality to 32-bit if we're doing an + i686-linux build on an x86_64-linux machine. */ + struct utsname utsbuf; + uname(&utsbuf); + if ((system == "i686-linux" + && (std::string_view(SYSTEM) == "x86_64-linux" + || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) + || system == "armv7l-linux" + || system == "armv6l-linux") + { + if (personality(PER_LINUX32) == -1) + throw SysError("cannot set 32-bit personality"); + } + + /* Impersonate a Linux 2.6 machine to get some determinism in + builds that depend on the kernel version. */ + if ((system == "i686-linux" || system == "x86_64-linux") && settings.impersonateLinux26) { + int cur = personality(0xffffffff); + if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */); + } + + /* Disable address space randomization for improved + determinism. */ + int cur = personality(0xffffffff); + if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE); +#endif +} + +} diff --git a/src/libstore/build/personality.hh b/src/libstore/build/personality.hh new file mode 100644 index 000000000..30e4f4062 --- /dev/null +++ b/src/libstore/build/personality.hh @@ -0,0 +1,11 @@ +#pragma once + +#include <string> + +namespace nix { + +void setPersonality(std::string_view system); + +} + + diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc index 47458a388..b1fbda13d 100644 --- a/src/libstore/builtins/buildenv.cc +++ b/src/libstore/builtins/buildenv.cc @@ -95,7 +95,7 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir, throw Error( "files '%1%' and '%2%' have the same priority %3%; " "use 'nix-env --set-flag priority NUMBER INSTALLED_PKGNAME' " - "or type 'nix profile install --help' if using 'nix profile' to find out how" + "or type 'nix profile install --help' if using 'nix profile' to find out how " "to change the priority of one of the conflicting packages" " (0 being the highest priority)", srcFile, readLink(dstFile), priority); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 274a15dd7..f4d53757c 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -329,7 +329,7 @@ public: Whether to execute builds inside cgroups. This is only supported on Linux. - Cgroups are required and enabled automatically for derivations + Cgroups are required and enabled automatically for derivations that require the `uid-range` system feature. > **Warning** @@ -491,6 +491,9 @@ public: for example, `/dev/nvidiactl?` specifies that `/dev/nvidiactl` will only be mounted in the sandbox if it exists in the host filesystem. + If the source is in the Nix store, then its closure will be added to + the sandbox as well. + Depending on how Nix was built, the default value for this option may be empty or provide `/bin/sh` as a bind-mount of `bash`. )", diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index b67668e52..3bab10af9 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -91,6 +91,7 @@ void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd) if (!lockFile(lockFd.get(), ltWrite, false)) { printInfo("waiting for exclusive access to the Nix store for ca drvs..."); + lockFile(lockFd.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks lockFile(lockFd.get(), ltWrite, true); } @@ -299,6 +300,7 @@ LocalStore::LocalStore(const Params & params) if (!lockFile(globalLock.get(), ltWrite, false)) { printInfo("waiting for exclusive access to the Nix store..."); + lockFile(globalLock.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks lockFile(globalLock.get(), ltWrite, true); } diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index f4ea739b0..3e0689534 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -166,16 +166,37 @@ public: return i->second; } + std::optional<Cache> queryCacheRaw(State & state, const std::string & uri) + { + auto i = state.caches.find(uri); + if (i == state.caches.end()) { + auto queryCache(state.queryCache.use()(uri)(time(0) - cacheInfoTtl)); + if (!queryCache.next()) + return std::nullopt; + state.caches.emplace(uri, + Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)}); + } + return getCache(state, uri); + } + void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) override { retrySQLite<void>([&]() { auto state(_state.lock()); + SQLiteTxn txn(state->db); + + // To avoid the race, we have to check if maybe someone hasn't yet created + // the cache for this URI in the meantime. + auto cache(queryCacheRaw(*state, uri)); - // FIXME: race + if (cache) + return; state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority).exec(); assert(sqlite3_changes(state->db) == 1); state->caches[uri] = Cache{(int) sqlite3_last_insert_rowid(state->db), storeDir, wantMassQuery, priority}; + + txn.commit(); }); } @@ -183,21 +204,12 @@ public: { return retrySQLite<std::optional<CacheInfo>>([&]() -> std::optional<CacheInfo> { auto state(_state.lock()); - - auto i = state->caches.find(uri); - if (i == state->caches.end()) { - auto queryCache(state->queryCache.use()(uri)(time(0) - cacheInfoTtl)); - if (!queryCache.next()) - return std::nullopt; - state->caches.emplace(uri, - Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)}); - } - - auto & cache(getCache(*state, uri)); - + auto cache(queryCacheRaw(*state, uri)); + if (!cache) + return std::nullopt; return CacheInfo { - .wantMassQuery = cache.wantMassQuery, - .priority = cache.priority + .wantMassQuery = cache->wantMassQuery, + .priority = cache->priority }; }); } diff --git a/src/libutil/canon-path.hh b/src/libutil/canon-path.hh index c5e7f0596..9d5984584 100644 --- a/src/libutil/canon-path.hh +++ b/src/libutil/canon-path.hh @@ -110,7 +110,7 @@ public: std::optional<std::string_view> dirOf() const { if (isRoot()) return std::nullopt; - return path.substr(0, path.rfind('/')); + return ((std::string_view) path).substr(0, path.rfind('/')); } std::optional<std::string_view> baseName() const diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 6c3a9c6c6..1d90d1dac 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -164,6 +164,14 @@ struct BuildEnvironment { return vars == other.vars && bashFunctions == other.bashFunctions; } + + std::string getSystem() const + { + if (auto v = get(vars, "system")) + return getString(*v); + else + return settings.thisSystem; + } }; const static std::string getEnvSh = @@ -570,7 +578,7 @@ struct CmdDevelop : Common, MixEnvironment } } - runProgramInStore(store, shell, args); + runProgramInStore(store, shell, args, buildEnvironment.getSystem()); } }; diff --git a/src/nix/run.cc b/src/nix/run.cc index 45d2dfd0d..6fca68047 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -9,6 +9,7 @@ #include "fs-accessor.hh" #include "progress-bar.hh" #include "eval.hh" +#include "build/personality.hh" #if __linux__ #include <sys/mount.h> @@ -24,7 +25,8 @@ namespace nix { void runProgramInStore(ref<Store> store, const std::string & program, - const Strings & args) + const Strings & args, + std::optional<std::string_view> system) { stopProgressBar(); @@ -44,7 +46,7 @@ void runProgramInStore(ref<Store> store, throw Error("store '%s' is not a local store so it does not support command execution", store->getUri()); if (store->storeDir != store2->getRealStoreDir()) { - Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program }; + Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), std::string(system.value_or("")), program }; for (auto & arg : args) helperArgs.push_back(arg); execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data()); @@ -52,6 +54,9 @@ void runProgramInStore(ref<Store> store, throw SysError("could not execute chroot helper"); } + if (system) + setPersonality(*system); + execvp(program.c_str(), stringsToCharPtrs(args).data()); throw SysError("unable to execute '%s'", program); @@ -199,6 +204,7 @@ void chrootHelper(int argc, char * * argv) int p = 1; std::string storeDir = argv[p++]; std::string realStoreDir = argv[p++]; + std::string system = argv[p++]; std::string cmd = argv[p++]; Strings args; while (p < argc) @@ -262,6 +268,9 @@ void chrootHelper(int argc, char * * argv) writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1)); writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1)); + if (system != "") + setPersonality(system); + execvp(cmd.c_str(), stringsToCharPtrs(args).data()); throw SysError("unable to exec '%s'", cmd); diff --git a/src/nix/run.hh b/src/nix/run.hh index 6180a87dd..fed360158 100644 --- a/src/nix/run.hh +++ b/src/nix/run.hh @@ -6,6 +6,7 @@ namespace nix { void runProgramInStore(ref<Store> store, const std::string & program, - const Strings & args); + const Strings & args, + std::optional<std::string_view> system = std::nullopt); } |