From b0818ff551f716d566dbf2dbe575a3321cf6dbef Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Sat, 17 Jul 2021 20:07:15 +0200 Subject: [PATCH] nixos/nscd: disable, provide NSS modules globally NSS modules are now globally provided (by providing a `/run/nss-modules` symlink), similar to how we handle OpenGL drivers. This removes the need for nscd as a proxy for all NSS requests, and avoids DNS requests leaking across network namespaces. While doing this upgrade, existing applications need to be restarted, so they know how to pick up NSS modules from `/run/nss-modules`. If you want to defer application restart to a later time, explicitly enable `nscd` via `services.nscd.enable` until the application restart. We can mix NSS modules from any version of glibc according to https://sourceware.org/legacy-ml/libc-help/2016-12/msg00008.html, so glibc upgrades shouldn't break old userland loading more recent NSS modules (and most likely, NSS modules are already loaded) 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 --- .../from_md/release-notes/rl-2111.section.xml | 30 +++++++++++ .../manual/release-notes/rl-2111.section.md | 17 +++++++ nixos/modules/config/nsswitch.nix | 50 +++++------------- nixos/modules/services/system/nscd.conf | 8 --- nixos/modules/services/system/nscd.nix | 16 +++--- nixos/modules/system/boot/resolved.nix | 1 - nixos/tests/resolv.nix | 1 - ...-loading-NSS-modules-from-run-nss-mo.patch | 51 +++++++++++++++++++ pkgs/development/libraries/glibc/common.nix | 2 + 9 files changed, 120 insertions(+), 56 deletions(-) create mode 100644 pkgs/development/libraries/glibc/0001-nss_module.c-try-loading-NSS-modules-from-run-nss-mo.patch diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index 1b0371a0179a8..65ad02a9a6821 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -1055,6 +1055,36 @@ Superuser created successfully. + + + NSS modules are now globally provided (by a + /run/nss-modules symlink), similar to how + we handle OpenGL drivers. + + + This removes the need for nscd as a proxy for all NSS + requests, and avoids DNS requests leaking across network + namespaces. + + + While doing this upgrade, existing applications need to be + restarted, so they know how to pick up NSS modules from + /run/nss-modules. + + + If you want to defer application restart to a later time, + explicitly enable nscd via + services.nscd.enable until the application + restart. + + + We can mix NSS modules from any version of glibc according to + https://sourceware.org/legacy-ml/libc-help/2016-12/msg00008.html, + so future glibc upgrades shouldn’t break old userland loading + more recent NSS modules (and most likely, NSS modules are + already loaded) + + The diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index 3df77d21d8276..4ee9d36ee4adf 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -307,6 +307,23 @@ To be able to access the web UI this port needs to be opened in the firewall. `myhostname`, but before `dns` should use the default priority - NSS modules which should come after `dns` should use mkAfter. +- NSS modules are now globally provided (by a `/run/nss-modules` symlink), + similar to how we handle OpenGL drivers. + + This removes the need for nscd as a proxy for all NSS requests, and avoids + DNS requests leaking across network namespaces. + + While doing this upgrade, existing applications need to be restarted, so + they know how to pick up NSS modules from `/run/nss-modules`. + + If you want to defer application restart to a later time, explicitly enable + `nscd` via `services.nscd.enable` until the application restart. + + We can mix NSS modules from any version of glibc according to + https://sourceware.org/legacy-ml/libc-help/2016-12/msg00008.html, + so future glibc upgrades shouldn't break old userland loading more recent NSS + modules (and most likely, NSS modules are already loaded) + - The [networking.wireless.iwd](options.html#opt-networking.wireless.iwd.enable) module has a new [networking.wireless.iwd.settings](options.html#opt-networking.wireless.iwd.settings) option. - The [services.syncoid.enable](options.html#opt-services.syncoid.enable) module now properly drops ZFS permissions after usage. Before it delegated permissions to whole pools instead of datasets and didn't clean up after execution. You can manually look this up for your pools by running `zfs allow your-pool-name` and use `zfs unallow syncoid your-pool-name` to clean this up. diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix index d109be47edcc3..51ea309a29850 100644 --- a/nixos/modules/config/nsswitch.nix +++ b/nixos/modules/config/nsswitch.nix @@ -6,13 +6,10 @@ with lib; { options = { - - # NSS modules. Hacky! - # Only works with nscd! system.nssModules = mkOption { type = types.listOf types.path; internal = true; - default = []; + default = [ ]; description = '' Path containing NSS (Name Service Switch) modules. This allows several DNS resolution methods to be specified via @@ -34,60 +31,40 @@ 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 = []; + default = [ ]; }; group = mkOption { 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 = []; + default = [ ]; }; shadow = mkOption { 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 = []; + default = [ ]; }; hosts = mkOption { 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 = []; + default = [ ]; }; services = mkOption { 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 = []; + default = [ ]; }; }; }; @@ -97,14 +74,13 @@ 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 /run/nss-modules + # We can mix NSS modules from any version of glibc according to + # https://sourceware.org/legacy-ml/libc-help/2016-12/msg00008.html, + # so glibc upgrades shouldn't break old userland loading more recent NSS + # modules (and most likely, NSS modules are already loaded) + systemd.tmpfiles.rules = [ + "L+ /run/nss-modules - - - - ${config.system.nssModules.path}" ]; # Name Service Switch configuration file. Required by the C 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 d720f254b8135..88ddc35ea856b 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" @@ -23,11 +22,9 @@ in enable = mkOption { type = types.bool; - default = true; + default = false; 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. ''; }; @@ -48,12 +45,11 @@ in environment.etc."nscd.conf".text = cfg.config; systemd.services.nscd = - { description = "Name Service Cache Daemon"; + { + description = "Name Service Cache Daemon"; 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 @@ -67,14 +63,16 @@ in # files. So prefix the ExecStart command with "!" to prevent systemd # from dropping privileges early. See ExecStart in systemd.service(5). serviceConfig = - { ExecStart = "!@${nscd}/sbin/nscd nscd"; + { + ExecStart = "!@${nscd}/sbin/nscd nscd"; Type = "forking"; DynamicUser = true; RuntimeDirectory = "nscd"; PIDFile = "/run/nscd/nscd.pid"; Restart = "always"; ExecReload = - [ "${nscd}/sbin/nscd --invalidate passwd" + [ + "${nscd}/sbin/nscd --invalidate passwd" "${nscd}/sbin/nscd --invalidate group" "${nscd}/sbin/nscd --invalidate hosts" ]; 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/0001-nss_module.c-try-loading-NSS-modules-from-run-nss-mo.patch b/pkgs/development/libraries/glibc/0001-nss_module.c-try-loading-NSS-modules-from-run-nss-mo.patch new file mode 100644 index 0000000000000..e474bd21d591a --- /dev/null +++ b/pkgs/development/libraries/glibc/0001-nss_module.c-try-loading-NSS-modules-from-run-nss-mo.patch @@ -0,0 +1,51 @@ +From 65a211ee3604733dceba13062f956256a573f27c Mon Sep 17 00:00:00 2001 +From: Florian Klink +Date: Sun, 19 Sep 2021 13:26:33 +0200 +Subject: [PATCH] nss_module.c: try loading NSS modules from /run/nss-modules + as a fallback + +On NixOS, glibc only looks for NSS modules in ${glibc.out}/lib, and what +LD_LIBRARY_PATH is set to. + +LD_LIBRARY_PATH is very invasive, so we don't want to set that globally. +We previously worked this around by running nscd with LD_LIBRARY_PATH +set, but nscd has some caching issues, and leak of resolution traffic, +so it's cleaner to have glibc look for NSS modules in an additional +path, that's provided by NixOS. + +On non-NixOS distributions, this shouldn't change behaviour, as the path +doesn't exist there. +--- + nss/nss_module.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/nss/nss_module.c b/nss/nss_module.c +index 6c5f341f..44cfc2a4 100644 +--- a/nss/nss_module.c ++++ b/nss/nss_module.c +@@ -133,6 +133,22 @@ module_load (struct nss_module *module) + return false; + + handle = __libc_dlopen (shlib_name); ++ ++ /* After loading from the default locations, try loading from ++ /run/nss-modules, to allow loading NixOS-provided NSS modules. */ ++ if(handle == NULL) ++ { ++ const char *nix_glibc_nss_path = "/run/nss-modules/"; ++ char shlib_path[1024]; ++ size_t shlib_pathlen = strlen(nix_glibc_nss_path) + strlen(shlib_name); ++ ++ if (shlib_pathlen < sizeof (shlib_path)) ++ { ++ __stpcpy (__stpcpy (&shlib_path[0], nix_glibc_nss_path), shlib_name); ++ handle = __libc_dlopen (shlib_path); ++ } ++ } ++ + free (shlib_name); + } + +-- +2.32.0 + diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix index e651a8effac99..dc139422f2e10 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 + + ./0001-nss_module.c-try-loading-NSS-modules-from-run-nss-mo.patch ] ++ lib.optional stdenv.hostPlatform.isMusl ./fix-rpc-types-musl-conflicts.patch ++ lib.optional stdenv.buildPlatform.isDarwin ./darwin-cross-build.patch;