aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/globals.cc
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2023-02-01 17:24:14 +0100
committerRobert Hensing <robert@roberthensing.nl>2023-04-07 16:24:18 +0200
commite706ffa007120249deace149dc4ba7cacf2c8beb (patch)
tree339c9e7656ec8096de4302050156682d125d0433 /src/libstore/globals.cc
parenta58be394769fb174ee4b6ff5ce16744cf5806485 (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.cc44
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;
}