about summary refs log tree commit diff
path: root/src/libstore
diff options
context:
space:
mode:
authorDan Peebles <pumpkin@me.com>2018-01-23T19·13-0500
committerDan Peebles <pumpkin@me.com>2018-01-23T19·45-0500
commitd43a8b25f044dffdbdd94777924e270cae3e0c8f (patch)
treefa9d2f7d74bd95fd2c9919b3f4d342098bf4fde6 /src/libstore
parentc382866cd26e19900c638e3724af89cf599f1f46 (diff)
Fix obscure corner case in name resolution for builtin:fetchurl in sandboxed environments
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build.cc17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 55066205db3a..cca51f17ee26 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -6,6 +6,7 @@
 #include "archive.hh"
 #include "affinity.hh"
 #include "builtins.hh"
+#include "download.hh"
 #include "finally.hh"
 #include "compression.hh"
 #include "json.hh"
@@ -1777,6 +1778,19 @@ PathSet exportReferences(Store & store, PathSet storePaths)
     return paths;
 }
 
+static std::once_flag dns_resolve_flag;
+
+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 download of an invalid URL to force the NSS machinery to
+       load its lookup libraries in the parent before any child gets a chance to. */
+    std::call_once(dns_resolve_flag, []() {
+        DownloadRequest request("http://this.pre-initializes.the.dns.resolvers.invalid");
+        request.tries = 1; // We only need to do it once, and this also suppresses an annoying warning
+        try { getDownloader()->download(request); } catch (...) {}
+    });
+}
 
 void DerivationGoal::startBuilder()
 {
@@ -1787,6 +1801,9 @@ void DerivationGoal::startBuilder()
             % drv->platform % settings.thisSystem % drvPath);
     }
 
+    if (drv->isBuiltin())
+        preloadNSS();
+
 #if __APPLE__
     additionalSandboxProfile = get(drv->env, "__sandboxProfile");
 #endif