diff options
author | Robert Hensing <robert@roberthensing.nl> | 2023-02-01 17:24:14 +0100 |
---|---|---|
committer | Robert Hensing <robert@roberthensing.nl> | 2023-04-07 16:24:18 +0200 |
commit | e706ffa007120249deace149dc4ba7cacf2c8beb (patch) | |
tree | 339c9e7656ec8096de4302050156682d125d0433 /src/libstore/globals.cc | |
parent | a58be394769fb174ee4b6ff5ce16744cf5806485 (diff) |
Move preloadNSS() from initNix to initLibStore
It is required for the sandbox, which is a libstore responsibility;
not just libmain.
Part of an effort to make it easier to initialize the right things,
by moving code into the appropriate libraries.
Diffstat (limited to 'src/libstore/globals.cc')
-rw-r--r-- | src/libstore/globals.cc | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 1e66838c5..6848991a2 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -7,6 +7,7 @@ #include <algorithm> #include <map> +#include <mutex> #include <thread> #include <dlfcn.h> #include <sys/utsname.h> @@ -15,6 +16,11 @@ #include <sodium/core.h> +#ifdef __GLIBC__ +#include <gnu/lib-names.h> +#include <nss.h> +#include <dlfcn.h> +#endif namespace nix { @@ -283,6 +289,42 @@ void initPlugins() settings.pluginFiles.pluginsLoaded = true; } +static void preloadNSS() +{ + /* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of + one of the glibc NSS libraries in a sandboxed child, which will fail unless the library's already + been loaded in the parent. So we force a lookup of an invalid domain to force the NSS machinery to + load its lookup libraries in the parent before any child gets a chance to. */ + static std::once_flag dns_resolve_flag; + + std::call_once(dns_resolve_flag, []() { +#ifdef __GLIBC__ + /* On linux, glibc will run every lookup through the nss layer. + * That means every lookup goes, by default, through nscd, which acts as a local + * cache. + * Because we run builds in a sandbox, we also remove access to nscd otherwise + * lookups would leak into the sandbox. + * + * But now we have a new problem, we need to make sure the nss_dns backend that + * does the dns lookups when nscd is not available is loaded or available. + * + * We can't make it available without leaking nix's environment, so instead we'll + * load the backend, and configure nss so it does not try to run dns lookups + * through nscd. + * + * This is technically only used for builtins:fetch* functions so we only care + * about dns. + * + * All other platforms are unaffected. + */ + if (!dlopen(LIBNSS_DNS_SO, RTLD_NOW)) + warn("unable to load nss_dns backend"); + // FIXME: get hosts entry from nsswitch.conf. + __nss_configure_lookup("hosts", "files dns"); +#endif + }); +} + static bool initLibStoreDone = false; void assertLibStoreInitialized() { @@ -299,6 +341,8 @@ void initLibStore() { loadConfFile(); + preloadNSS(); + initLibStoreDone = true; } |