From da3471fc772e123137d01d31b3e35944657c308b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 29 Jan 2021 20:19:57 +0100 Subject: [PATCH] glibc: Add an environment variable for specifying an NSS search path With this, you can set $NIX_GLIBC_NSS_PATH to a colon-separated list of directories in which glibc will look for NSS modules. In environments where nscd cannot be used, this allows dealing with non-standard NSS modules in a less sledgehammer-y way than setting $LD_LIBRARY_PATH (which affects everything, and in particular could cause ABI incompatibilities). The default value is /nix/run/glibc-nss-path/${out-hash}:/nix/run/glibc-nss-path where out-hash is the hash part of glibc.out (e.g. /nix/run/glibc-nss-path/0cjq75a1cgwd7ccxsp9warzjax1kr7ag). Thus, glibc will look for an NSS module named libnss_mymachines.so.2 at /nix/run/glibc-nss-path/0cjq75a1cgwd7ccxsp9warzjax1kr7ag/libnss_mymachines.so.2 and /nix/run/glibc-nss-path/libnss_mymachines.so.2 These are tried *after* the default search locations (i.e. $LD_LIBRARY_PATH and glibc.out/lib) so they don't override any current behaviour. The use of /nix/run rather than /run is because the user may have write access to /nix but not to /run. On NixOS, it's intended than /nix/run is a symlink / bind-mount to /run. --- nixos/modules/services/system/nscd.nix | 2 +- pkgs/development/libraries/glibc/common.nix | 2 + pkgs/development/libraries/glibc/default.nix | 6 +++ .../libraries/glibc/nss-path.patch | 50 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 pkgs/development/libraries/glibc/nss-path.patch diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix index d720f254b8135..2954dcfe9e53f 100644 --- a/nixos/modules/services/system/nscd.nix +++ b/nixos/modules/services/system/nscd.nix @@ -52,7 +52,7 @@ in wantedBy = [ "nss-lookup.target" "nss-user-lookup.target" ]; - environment = { LD_LIBRARY_PATH = nssModulesPath; }; + environment = { NIX_GLIBC_NSS_PATH = nssModulesPath; }; restartTriggers = [ config.environment.etc.hosts.source diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix index 54882ba671857..9725adb5628d8 100644 --- a/pkgs/development/libraries/glibc/common.nix +++ b/pkgs/development/libraries/glibc/common.nix @@ -119,6 +119,8 @@ stdenv.mkDerivation ({ }) ./fix-x64-abi.patch + + ./nss-path.patch ] ++ lib.optional stdenv.hostPlatform.isMusl ./fix-rpc-types-musl-conflicts.patch ++ lib.optional stdenv.buildPlatform.isDarwin ./darwin-cross-build.patch; diff --git a/pkgs/development/libraries/glibc/default.nix b/pkgs/development/libraries/glibc/default.nix index 9043c8fd0d4f3..9fd3a22b79c2a 100644 --- a/pkgs/development/libraries/glibc/default.nix +++ b/pkgs/development/libraries/glibc/default.nix @@ -62,6 +62,12 @@ callPackage ./common.nix { inherit stdenv; } { ]) ]); + preHook = + '' + outName=$(basename $out) + NIX_CFLAGS_COMPILE+=" -DDEFAULT_NSS_PATH=\"${dirOf builtins.storeDir}/run/glibc-nss-path/''${outName:0:32}:${dirOf builtins.storeDir}/run/glibc-nss-path\""; + ''; + # When building glibc from bootstrap-tools, we need libgcc_s at RPATH for # any program we run, because the gcc will have been placed at a new # store path than that determined when built (as a source for the diff --git a/pkgs/development/libraries/glibc/nss-path.patch b/pkgs/development/libraries/glibc/nss-path.patch new file mode 100644 index 0000000000000..5145513376a75 --- /dev/null +++ b/pkgs/development/libraries/glibc/nss-path.patch @@ -0,0 +1,50 @@ +diff -ru -x '*~' glibc-2.32-orig/nss/nsswitch.c glibc-2.32/nss/nsswitch.c +--- glibc-2.32-orig/nss/nsswitch.c 2020-08-05 04:17:00.000000000 +0200 ++++ glibc-2.32/nss/nsswitch.c 2021-01-29 19:40:50.730883061 +0100 +@@ -349,6 +349,35 @@ + __nss_shlib_revision); + + ni->library->lib_handle = __libc_dlopen (shlib_name); ++ ++ if (ni->library->lib_handle == NULL) ++ { ++ const char *nss_path = __libc_secure_getenv ("NIX_GLIBC_NSS_PATH"); ++ if (!nss_path) ++ nss_path = DEFAULT_NSS_PATH; ++ ++ const char *pos = nss_path; ++ ++ while (*pos) ++ { ++ const char *end = __strchrnul(pos, ':'); ++ if (pos != end) ++ { ++ char shlib_path[1024]; ++ size_t shlib_pathlen = (end - pos) + 1 + strlen (shlib_name) + 1; ++ if (shlib_pathlen < sizeof(shlib_path)) ++ { ++ __stpcpy (__stpcpy (__stpncpy (shlib_path, pos, end - pos), "/"), shlib_name); ++ ni->library->lib_handle = __libc_dlopen (shlib_path); ++ if (ni->library->lib_handle != NULL) ++ break; ++ } ++ if (!*end) break; ++ pos = end + 1; ++ } ++ } ++ } ++ + if (ni->library->lib_handle == NULL) + { + /* Failed to load the library. */ +diff -ru -x '*~' glibc-2.32-orig/sysdeps/generic/unsecvars.h glibc-2.32/sysdeps/generic/unsecvars.h +--- glibc-2.32-orig/sysdeps/generic/unsecvars.h 2020-08-05 04:17:00.000000000 +0200 ++++ glibc-2.32/sysdeps/generic/unsecvars.h 2021-01-29 15:38:37.067684060 +0100 +@@ -27,6 +27,7 @@ + "LOCPATH\0" \ + "MALLOC_TRACE\0" \ + "NIS_PATH\0" \ ++ "NIX_GLIBC_NSS_PATH\0" \ + "NLSPATH\0" \ + "RESOLV_HOST_CONF\0" \ + "RES_OPTIONS\0" \