From 0da59460d282059a38bc4cb8712e376edbff0725 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Sat, 17 Jul 2021 20:07:15 +0200 Subject: [PATCH] nixos: allow providing NSS modules without nscd NSS modules are now globally provided by a symlink in `/run`. See the description in `add-extra-module-load-path.patch` for further details. Fixes: https://github.com/NixOS/nixpkgs/issues/55276 Fixes: https://github.com/NixOS/nixpkgs/issues/135888 Fixes: https://github.com/NixOS/nixpkgs/issues/105353 Cc: https://github.com/NixOS/nixpkgs/issues/52411#issuecomment-757347201 Co-authored-by: Erik Arvstedt --- nixos/modules/config/nsswitch.nix | 36 ++------- .../services/network-filesystems/samba.nix | 4 - .../services/networking/avahi-daemon.nix | 4 - .../modules/services/networking/ssh/lshd.nix | 4 - .../modules/services/networking/ssh/sshd.nix | 3 - nixos/modules/services/system/dbus.nix | 1 - nixos/modules/services/system/nscd.conf | 8 -- nixos/modules/services/system/nscd.nix | 5 -- nixos/modules/system/boot/resolved.nix | 1 - nixos/tests/resolv.nix | 1 - .../glibc/add-extra-module-load-path.patch | 75 +++++++++++++++++++ pkgs/development/libraries/glibc/common.nix | 2 + 12 files changed, 82 insertions(+), 62 deletions(-) create mode 100644 pkgs/development/libraries/glibc/add-extra-module-load-path.patch diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix index fb45664e44e12..c3e7b867a86f4 100644 --- a/nixos/modules/config/nsswitch.nix +++ b/nixos/modules/config/nsswitch.nix @@ -6,9 +6,6 @@ with lib; { options = { - - # NSS modules. Hacky! - # Only works with nscd! system.nssModules = mkOption { type = types.listOf types.path; internal = true; @@ -33,10 +30,6 @@ with lib; type = types.listOf types.str; description = '' List of passwd entries to configure in /etc/nsswitch.conf. - - Note that "files" is always prepended while "systemd" is appended if nscd is enabled. - - This option only takes effect if nscd is enabled. ''; default = []; }; @@ -45,10 +38,6 @@ with lib; type = types.listOf types.str; description = '' List of group entries to configure in /etc/nsswitch.conf. - - Note that "files" is always prepended while "systemd" is appended if nscd is enabled. - - This option only takes effect if nscd is enabled. ''; default = []; }; @@ -57,10 +46,6 @@ with lib; type = types.listOf types.str; description = '' List of shadow entries to configure in /etc/nsswitch.conf. - - Note that "files" is always prepended. - - This option only takes effect if nscd is enabled. ''; default = []; }; @@ -69,10 +54,6 @@ with lib; type = types.listOf types.str; description = '' List of hosts entries to configure in /etc/nsswitch.conf. - - Note that "files" is always prepended, and "dns" and "myhostname" are always appended. - - This option only takes effect if nscd is enabled. ''; default = []; }; @@ -81,10 +62,6 @@ with lib; type = types.listOf types.str; description = '' List of services entries to configure in /etc/nsswitch.conf. - - Note that "files" is always prepended. - - This option only takes effect if nscd is enabled. ''; default = []; }; @@ -96,14 +73,11 @@ with lib; ]; config = { - assertions = [ - { - # Prevent users from disabling nscd, with nssModules being set. - # If disabling nscd is really necessary, it's still possible to opt out - # by forcing config.system.nssModules to []. - assertion = config.system.nssModules.path != "" -> config.services.nscd.enable; - message = "Loading NSS modules from system.nssModules (${config.system.nssModules.path}), requires services.nscd.enable being set to true."; - } + # Provide configured NSS modules at a platform-specific path in /run + systemd.tmpfiles.rules = let + glibcPlatform = "${if pkgs.stdenv.hostPlatform.is64bit then "64" else "32"}-${pkgs.glibc.version}"; + in [ + "L+ /run/nss-modules${glibcPlatform} - - - - ${config.system.nssModules.path}" ]; # Name Service Switch configuration file. Required by the C diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix index 78ea245cb3519..1154b21fdad51 100644 --- a/nixos/modules/services/network-filesystems/samba.nix +++ b/nixos/modules/services/network-filesystems/samba.nix @@ -33,9 +33,6 @@ let ${smbToString (map shareConfig (attrNames cfg.shares))} ''); - # This may include nss_ldap, needed for samba if it has to use ldap. - nssModulesPath = config.system.nssModules.path; - daemonService = appName: args: { description = "Samba Service Daemon ${appName}"; @@ -44,7 +41,6 @@ let partOf = [ "samba.target" ]; environment = { - LD_LIBRARY_PATH = nssModulesPath; LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; }; diff --git a/nixos/modules/services/networking/avahi-daemon.nix b/nixos/modules/services/networking/avahi-daemon.nix index 020a817f25961..c58202c1427fb 100644 --- a/nixos/modules/services/networking/avahi-daemon.nix +++ b/nixos/modules/services/networking/avahi-daemon.nix @@ -264,10 +264,6 @@ in wantedBy = [ "multi-user.target" ]; requires = [ "avahi-daemon.socket" ]; - # Make NSS modules visible so that `avahi_nss_support ()' can - # return a sensible value. - environment.LD_LIBRARY_PATH = config.system.nssModules.path; - path = [ pkgs.coreutils pkgs.avahi ]; serviceConfig = { diff --git a/nixos/modules/services/networking/ssh/lshd.nix b/nixos/modules/services/networking/ssh/lshd.nix index 862ff7df05407..e1eba3a7a8f07 100644 --- a/nixos/modules/services/networking/ssh/lshd.nix +++ b/nixos/modules/services/networking/ssh/lshd.nix @@ -137,10 +137,6 @@ in wantedBy = [ "multi-user.target" ]; - environment = { - LD_LIBRARY_PATH = config.system.nssModules.path; - }; - preStart = '' test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index 225aee5160503..89adc40379394 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -24,8 +24,6 @@ let cfg = config.services.openssh; cfgc = config.programs.ssh; - nssModulesPath = config.system.nssModules.path; - userOptions = { options.openssh.authorizedKeys = { @@ -421,7 +419,6 @@ in after = [ "network.target" ]; stopIfChanged = false; path = [ cfgc.package pkgs.gawk ]; - environment.LD_LIBRARY_PATH = nssModulesPath; restartTriggers = optionals (!cfg.startWhenNeeded) [ config.environment.etc."ssh/sshd_config".source diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index d4cacb85694b9..f7ab64630610b 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -122,7 +122,6 @@ in # Don't restart dbus-daemon. Bad things tend to happen if we do. reloadIfChanged = true; restartTriggers = [ configDir ]; - environment = { LD_LIBRARY_PATH = config.system.nssModules.path; }; }; systemd.user = { diff --git a/nixos/modules/services/system/nscd.conf b/nixos/modules/services/system/nscd.conf index 722b883ba420b..eb9c48ded1266 100644 --- a/nixos/modules/services/system/nscd.conf +++ b/nixos/modules/services/system/nscd.conf @@ -1,11 +1,3 @@ -# We basically use nscd as a proxy for forwarding nss requests to appropriate -# nss modules, as we run nscd with LD_LIBRARY_PATH set to the directory -# containing all such modules -# Note that we can not use `enable-cache no` As this will actually cause nscd -# to just reject the nss requests it receives, which then causes glibc to -# fallback to trying to handle the request by itself. Which won't work as glibc -# is not aware of the path in which the nss modules live. As a workaround, we -# have `enable-cache yes` with an explicit ttl of 0 server-user nscd enable-cache passwd yes diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix index 7d05acfc14b87..1d7229d110753 100644 --- a/nixos/modules/services/system/nscd.nix +++ b/nixos/modules/services/system/nscd.nix @@ -4,7 +4,6 @@ with lib; let - nssModulesPath = config.system.nssModules.path; cfg = config.services.nscd; nscd = if pkgs.stdenv.hostPlatform.libc == "glibc" @@ -26,8 +25,6 @@ in default = true; description = '' Whether to enable the Name Service Cache Daemon. - Disabling this is strongly discouraged, as this effectively disables NSS Lookups - from all non-glibc NSS modules, including the ones provided by systemd. ''; }; @@ -53,8 +50,6 @@ in wantedBy = [ "nss-lookup.target" "nss-user-lookup.target" ]; - environment = { LD_LIBRARY_PATH = nssModulesPath; }; - restartTriggers = [ config.environment.etc.hosts.source config.environment.etc."nsswitch.conf".source diff --git a/nixos/modules/system/boot/resolved.nix b/nixos/modules/system/boot/resolved.nix index a6fc07da0abbf..36f9302a8e86a 100644 --- a/nixos/modules/system/boot/resolved.nix +++ b/nixos/modules/system/boot/resolved.nix @@ -138,7 +138,6 @@ in users.users.systemd-resolve.group = "systemd-resolve"; - # add resolve to nss hosts database if enabled and nscd enabled # system.nssModules is configured in nixos/modules/system/boot/systemd.nix # added with order 501 to allow modules to go before with mkBefore system.nssDatabases.hosts = (mkOrder 501 ["resolve [!UNAVAIL=return]"]); diff --git a/nixos/tests/resolv.nix b/nixos/tests/resolv.nix index f0aa7e42aaf35..5ff9491036bdd 100644 --- a/nixos/tests/resolv.nix +++ b/nixos/tests/resolv.nix @@ -29,7 +29,6 @@ import ./make-test-python.nix ({ pkgs, ... } : { start_all() - resolv.wait_for_unit("nscd") ipv4 = ["192.0.2.1", "192.0.2.2"] ipv6 = ["2001:db8::2:1", "2001:db8::2:2"] diff --git a/pkgs/development/libraries/glibc/add-extra-module-load-path.patch b/pkgs/development/libraries/glibc/add-extra-module-load-path.patch new file mode 100644 index 0000000000000..1ca8152681577 --- /dev/null +++ b/pkgs/development/libraries/glibc/add-extra-module-load-path.patch @@ -0,0 +1,75 @@ +Add NSS module load path /run/nss-modules${word_size}-${glibc_version}/lib + +If this path is not present at runtime, the behaviour of libc is unchanged. + +If this path is present: +- Don't use nscd +- Use this load path as a fallback after paths ${glibc.out}/lib and LD_LIBRARY_PATH + +On NixOS, this allows ABI-compatible glibc clients to directly load NSS modules +instead of using nscd for name service requests. +nscd has caching bugs and leaks DNS requests across network namespaces. + +nscd, if running, will still be used by ABI-incompatible glibc clients. +(Such as 32-bit binaries on a 64-bit host or binaries with older glibc versions.) +This guarantees full backwards compatibility. + +On non-NixOS systems, this shouldn't change behaviour, as the path +doesn't exist there. + +diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c +index 462504d8..65cca10d 100644 +--- a/nscd/nscd_helper.c ++++ b/nscd/nscd_helper.c +@@ -169,6 +169,12 @@ open_socket (request_type type, const char *key, size_t keylen) + { + int sock; + ++ /* Don't use nscd when the platform-specific NixOS module load path is present */ ++#include "../nss/nixos-nss-modules-path.h" ++ if (access(NIXOS_NSS_MODULES_PATH, F_OK) == 0) { ++ return -1; ++ } ++ + sock = __socket (PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (sock < 0) + return -1; +diff --git a/nss/nixos-nss-modules-path.h b/nss/nixos-nss-modules-path.h +new file mode 100644 +index 00000000..20a5643b +--- /dev/null ++++ b/nss/nixos-nss-modules-path.h +@@ -0,0 +1,3 @@ ++#define STR_(x) #x ++#define STR(x) STR_(x) ++#define NIXOS_NSS_MODULES_PATH "/run/nss-modules" STR(__WORDSIZE) "-" STR(__GLIBC__) "." STR(__GLIBC_MINOR__) "/lib/" +diff --git a/nss/nss_module.c b/nss/nss_module.c +index 6c5f341f..f5296507 100644 +--- a/nss/nss_module.c ++++ b/nss/nss_module.c +@@ -133,6 +133,25 @@ module_load (struct nss_module *module) + return false; + + handle = __libc_dlopen (shlib_name); ++ ++ /* After loading from the default locations, try loading from ++ the NixOS module load path. */ ++ if (handle == NULL) { ++ ++#include "nixos-nss-modules-path.h" ++ const char nix_nss_path[] = NIXOS_NSS_MODULES_PATH; ++ char shlib_path[1024]; ++ size_t nix_nss_path_len = sizeof(nix_nss_path) - 1; ++ size_t shlib_name_len = strlen(shlib_name); ++ size_t shlib_path_len = nix_nss_path_len + shlib_name_len; ++ ++ if (shlib_path_len < sizeof(shlib_path)) { ++ memcpy(&shlib_path[0], nix_nss_path, nix_nss_path_len); ++ memcpy(&shlib_path[nix_nss_path_len], shlib_name, shlib_name_len + 1); ++ handle = __libc_dlopen(shlib_path); ++ } ++ } ++ + free (shlib_name); + } + diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix index e651a8effac99..28c7721aeff16 100644 --- a/pkgs/development/libraries/glibc/common.nix +++ b/pkgs/development/libraries/glibc/common.nix @@ -120,6 +120,8 @@ stdenv.mkDerivation ({ }) ./fix-x64-abi.patch + + ./add-extra-module-load-path.patch ] ++ lib.optional stdenv.hostPlatform.isMusl ./fix-rpc-types-musl-conflicts.patch ++ lib.optional stdenv.buildPlatform.isDarwin ./darwin-cross-build.patch;