Merge pull request #5224 from baloo/baloo/5089/force-nss_dns-load

preloadNSS: fixup nss_dns load
This commit is contained in:
Eelco Dolstra 2021-09-09 10:37:41 +02:00 committed by GitHub
commit 1e43bc6dc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 24 deletions

View file

@ -15,6 +15,9 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
@ -110,6 +113,31 @@ static void opensslLockCallback(int mode, int type, const char * file, int line)
} }
#endif #endif
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 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. */
std::call_once(dns_resolve_flag, []() {
struct addrinfo *res = NULL;
/* nss will only force the "local" (not through nscd) dns resolution if its on the LOCALDOMAIN.
We need the resolution to be done locally, as nscd socket will not be accessible in the
sandbox. */
char * previous_env = getenv("LOCALDOMAIN");
setenv("LOCALDOMAIN", "invalid", 1);
if (getaddrinfo("this.pre-initializes.the.dns.resolvers.invalid.", "http", NULL, &res) == 0) {
if (res) freeaddrinfo(res);
}
if (previous_env) {
setenv("LOCALDOMAIN", previous_env, 1);
} else {
unsetenv("LOCALDOMAIN");
}
});
}
static void sigHandler(int signo) { } static void sigHandler(int signo) { }
@ -176,6 +204,8 @@ void initNix()
if (hasPrefix(getEnv("TMPDIR").value_or("/tmp"), "/var/folders/")) if (hasPrefix(getEnv("TMPDIR").value_or("/tmp"), "/var/folders/"))
unsetenv("TMPDIR"); unsetenv("TMPDIR");
#endif #endif
preloadNSS();
} }

View file

@ -17,10 +17,7 @@
#include <regex> #include <regex>
#include <queue> #include <queue>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <netdb.h>
#include <fcntl.h> #include <fcntl.h>
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
@ -34,7 +31,6 @@
/* Includes required for chroot support. */ /* Includes required for chroot support. */
#if __linux__ #if __linux__
#include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/ip.h> #include <netinet/ip.h>
@ -344,23 +340,6 @@ int childEntry(void * arg)
} }
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 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. */
std::call_once(dns_resolve_flag, []() {
struct addrinfo *res = NULL;
if (getaddrinfo("this.pre-initializes.the.dns.resolvers.invalid.", "http", NULL, &res) != 0) {
if (res) freeaddrinfo(res);
}
});
}
static void linkOrCopy(const Path & from, const Path & to) static void linkOrCopy(const Path & from, const Path & to)
{ {
if (link(from.c_str(), to.c_str()) == -1) { if (link(from.c_str(), to.c_str()) == -1) {
@ -389,9 +368,6 @@ void LocalDerivationGoal::startBuilder()
settings.thisSystem, settings.thisSystem,
concatStringsSep<StringSet>(", ", worker.store.systemFeatures)); concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
if (drv->isBuiltin())
preloadNSS();
#if __APPLE__ #if __APPLE__
additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or(""); additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or("");
#endif #endif