From 47a70fb50aa5adcbde9e283ee00c146e70875faa7d4a6bf70bdd276e1fc74563 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 8 Mar 2021 15:03:02 +0000 Subject: [PATCH] Accepting request 877767 from home:Andreas_Schwab:Factory - nss-database-check-reload.patch: nsswitch: return result when nss database is locked (BZ #27343) - nss-load-chroot.patch: nss: Re-enable NSS module loading after chroot (bsc#1182323, BZ #27389) - x86-isa-level.patch: x86: Set minimum x86-64 level marker (bsc#1182522, BZ #27318) - nss-database-lookup.patch: nss: fix nss_database_lookup2's alternate handling (bsc#1182247, BZ #27416) - nss-revert-api.patch: remove - nscd-netgroupcache.patch: nscd: Fix double free in netgroupcache (CVE-2021-27645, bsc#1182733, BZ #27462) OBS-URL: https://build.opensuse.org/request/show/877767 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=585 --- glibc-nsswitch-usr.diff | 26 +- glibc.changes | 15 + glibc.spec | 44 +- nscd-netgroupcache.patch | 42 + nss-database-check-reload.patch | 45 + nss-database-lookup.patch | 839 ++++++ nss-load-chroot.patch | 172 ++ nss-revert-api.patch | 4609 ------------------------------- x86-isa-level.patch | 183 ++ 9 files changed, 1334 insertions(+), 4641 deletions(-) create mode 100644 nscd-netgroupcache.patch create mode 100644 nss-database-check-reload.patch create mode 100644 nss-database-lookup.patch create mode 100644 nss-load-chroot.patch delete mode 100644 nss-revert-api.patch create mode 100644 x86-isa-level.patch diff --git a/glibc-nsswitch-usr.diff b/glibc-nsswitch-usr.diff index d88bf42..de104f5 100644 --- a/glibc-nsswitch-usr.diff +++ b/glibc-nsswitch-usr.diff @@ -1,15 +1,13 @@ -Index: glibc-2.33/nss/nsswitch.c +Index: glibc-2.33/nss/nss_database.c =================================================================== ---- glibc-2.33.orig/nss/nsswitch.c -+++ glibc-2.33/nss/nsswitch.c -@@ -126,6 +126,10 @@ __nss_database_lookup2 (const char *data - /* Read config file. */ - service_table = nss_parse_file (_PATH_NSSWITCH_CONF); - -+ /* Retry with the OS vendor provided config file. */ -+ if (service_table == NULL) -+ service_table = nss_parse_file ("/usr" _PATH_NSSWITCH_CONF); -+ - /* Test whether configuration data is available. */ - if (service_table != NULL) - { +--- glibc-2.33.orig/nss/nss_database.c ++++ glibc-2.33/nss/nss_database.c +@@ -303,6 +303,8 @@ nss_database_reload (struct nss_database + { + FILE *fp = fopen (_PATH_NSSWITCH_CONF, "rce"); + if (fp == NULL) ++ fp = fopen ("/usr" _PATH_NSSWITCH_CONF, "rce"); ++ if (fp == NULL) + switch (errno) + { + case EACCES: diff --git a/glibc.changes b/glibc.changes index ea0fd98..427fe31 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,18 @@ +------------------------------------------------------------------- +Mon Mar 8 10:43:30 UTC 2021 - Andreas Schwab + +- nss-database-check-reload.patch: nsswitch: return result when nss + database is locked (BZ #27343) +- nss-load-chroot.patch: nss: Re-enable NSS module loading after chroot + (bsc#1182323, BZ #27389) +- x86-isa-level.patch: x86: Set minimum x86-64 level marker (bsc#1182522, + BZ #27318) +- nss-database-lookup.patch: nss: fix nss_database_lookup2's alternate + handling (bsc#1182247, BZ #27416) +- nss-revert-api.patch: remove +- nscd-netgroupcache.patch: nscd: Fix double free in netgroupcache + (CVE-2021-27645, bsc#1182733, BZ #27462) + ------------------------------------------------------------------- Tue Mar 2 11:57:15 UTC 2021 - Andreas Schwab diff --git a/glibc.spec b/glibc.spec index ea1fa2e..e5a1fb2 100644 --- a/glibc.spec +++ b/glibc.spec @@ -90,9 +90,6 @@ BuildRequires: zlib-devel ExclusiveArch: i586 i686 BuildArch: i686 %endif -%if %{with usrmerged} && %{build_main} -Provides: /sbin/ldconfig -%endif %define __filter_GLIBC_PRIVATE 1 %ifarch i686 @@ -183,6 +180,9 @@ Provides: ld-linux.so.3(GLIBC_2.4) Requires(pre): filesystem Recommends: glibc-extra Provides: rtld(GNU_HASH) +%if %{with usrmerged} +Provides: /sbin/ldconfig +%endif %endif %if %{build_utils} Requires: glibc = %{version} @@ -200,8 +200,6 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build ### # Patches that upstream will not accept ### -# PATCH-FIX-OPENSUSE Work around for nss-compat brokeness -Patch1: nss-revert-api.patch ### # openSUSE specific patches - won't go upstream @@ -247,6 +245,14 @@ Patch306: glibc-fix-double-loopback.diff ### # Patches from upstream ### +# PATCH-FIX-UPSTREAM nsswitch: return result when nss database is locked (BZ #27343) +Patch1000: nss-database-check-reload.patch +# PATCH-FIX-UPSTREAM nss: Re-enable NSS module loading after chroot (BZ #27389) +Patch1001: nss-load-chroot.patch +# PATCH-FIX-UPSTREAM x86: Set minimum x86-64 level marker (BZ #27318) +Patch1002: x86-isa-level.patch +# PATCH-FIX-UPSTREAM nscd: Fix double free in netgroupcache (CVE-2021-27645, BZ #27462) +Patch1003: nscd-netgroupcache.patch ### # Patches awaiting upstream approval @@ -255,6 +261,8 @@ Patch306: glibc-fix-double-loopback.diff Patch2000: fix-locking-in-_IO_cleanup.patch # PATCH-FIX-UPSTREAM Avoid concurrency problem in ldconfig (BZ #23973) Patch2001: ldconfig-concurrency.patch +# PATCH-FIX-UPSTREAM nss: fix nss_database_lookup2's alternate handling (BZ #27416) +Patch2002: nss-database-lookup.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -445,7 +453,6 @@ Internal usrmerge bootstrap helper %prep %setup -n glibc-%{version} -q -a 4 -%patch1 -p1 %patch6 -p1 %patch7 -p1 %patch8 -p1 @@ -465,8 +472,14 @@ Internal usrmerge bootstrap helper %patch304 -p1 %patch306 -p1 +%patch1000 -p1 +%patch1001 -p1 +%patch1002 -p1 +%patch1003 -p1 + %patch2000 -p1 %patch2001 -p1 +%patch2002 -p1 %patch3000 @@ -503,16 +516,17 @@ echo "#define GITID \"%{git_id}\"" >> version.h # # Default CFLAGS and Compiler # -BuildFlags="%{optflags} -U_FORTIFY_SOURCE" enable_stack_protector= -for opt in $BuildFlags; do +BuildFlags= +tmp="%{optflags}" +for opt in $tmp; do case $opt in - -fstack-protector-strong) enable_stack_protector=strong ;; - -fstack-protector-all) enable_stack_protector=all ;; + -fstack-protector-*) enable_stack_protector=${opt#-fstack-protector-} ;; -fstack-protector) enable_stack_protector=yes ;; + -ffortify=* | *_FORTIFY_SOURCE*) ;; + *) BuildFlags+=" $opt" ;; esac done -BuildFlags=$(echo $BuildFlags | sed -e 's#-fstack-protector[^ ]*##' -e 's#-ffortify=[0-9]*##') BuildCC="%__cc" BuildCCplus="%__cxx" # @@ -547,10 +561,6 @@ BuildCCplus="%__cxx" %ifarch hppa BuildFlags="$BuildFlags -mpa-risc-1-1 -fstrict-aliasing" %endif -# Add flags for all plattforms except AXP -%ifnarch alpha - BuildFlags="$BuildFlags -g" -%endif %if %{disable_assert} BuildFlags="$BuildFlags -DNDEBUG=1" %endif @@ -565,7 +575,7 @@ BuildCCplus="%__cxx" mkdir cc-base cd cc-base %ifarch %arm aarch64 -# remove asynchronous-unwind-tables during configure as it causes +# remove [asynchronous-]unwind-tables during configure as it causes # some checks to fail spuriously on arm conf_cflags="${BuildFlags/-fasynchronous-unwind-tables/}" conf_cflags="${conf_cflags/-funwind-tables/}" @@ -578,8 +588,6 @@ profile="--enable-profile" %else profile="--disable-profile" %endif -# Disable x86 ISA level support for now (bsc#1182522) -export libc_cv_include_x86_isa_level=no ../configure \ CFLAGS="$conf_cflags" BUILD_CFLAGS="$conf_cflags" \ CC="$BuildCC" CXX="$BuildCCplus" \ diff --git a/nscd-netgroupcache.patch b/nscd-netgroupcache.patch new file mode 100644 index 0000000..dbb29e0 --- /dev/null +++ b/nscd-netgroupcache.patch @@ -0,0 +1,42 @@ +From a151f2e05a64727c552a297d129b8ef242ffb3b6 Mon Sep 17 00:00:00 2001 +From: DJ Delorie +Date: Thu, 25 Feb 2021 16:08:21 -0500 +Subject: [PATCH] nscd: Fix double free in netgroupcache [BZ #27462] + +In commit 745664bd798ec8fd50438605948eea594179fba1 a use-after-free +was fixed, but this led to an occasional double-free. This patch +tracks the "live" allocation better. + +Tested manually by a third party. + +Related: RHBZ 1927877 + +Reviewed-by: Siddhesh Poyarekar +Reviewed-by: Carlos O'Donell +(cherry picked from commit dca565886b5e8bd7966e15f0ca42ee5cff686673) +--- + nscd/netgroupcache.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: glibc-2.33/nscd/netgroupcache.c +=================================================================== +--- glibc-2.33.orig/nscd/netgroupcache.c ++++ glibc-2.33/nscd/netgroupcache.c +@@ -248,7 +248,7 @@ addgetnetgrentX (struct database_dyn *db + : NULL); + ndomain = (ndomain ? newbuf + ndomaindiff + : NULL); +- buffer = newbuf; ++ *tofreep = buffer = newbuf; + } + + nhost = memcpy (buffer + bufused, +@@ -319,7 +319,7 @@ addgetnetgrentX (struct database_dyn *db + else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) + { + buflen *= 2; +- buffer = xrealloc (buffer, buflen); ++ *tofreep = buffer = xrealloc (buffer, buflen); + } + else if (status == NSS_STATUS_RETURN + || status == NSS_STATUS_NOTFOUND diff --git a/nss-database-check-reload.patch b/nss-database-check-reload.patch new file mode 100644 index 0000000..4610613 --- /dev/null +++ b/nss-database-check-reload.patch @@ -0,0 +1,45 @@ +From 17f0ff097887008b2d3dca270c8ffbb4b43a8749 Mon Sep 17 00:00:00 2001 +From: Sergei Trofimovich +Date: Fri, 5 Feb 2021 07:32:18 +0000 +Subject: [PATCH] nsswitch: return result when nss database is locked [BZ + #27343] + +Before the change nss_database_check_reload_and_get() did not populate +the '*result' value when it returned success in a case of chroot +detection. This caused initgroups() to use garage pointer in the +following test (extracted from unbound): + +``` + +int main() { + // load some NSS modules + struct passwd * pw = getpwnam("root"); + + chdir("/tmp"); + chroot("/tmp"); + chdir("/"); + // access nsswitch.conf in a chroot + initgroups("root", 0); +} +``` + +Reviewed-by: DJ Delorie +--- + nss/nss_database.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: glibc-2.33/nss/nss_database.c +=================================================================== +--- glibc-2.33.orig/nss/nss_database.c ++++ glibc-2.33/nss/nss_database.c +@@ -400,8 +400,9 @@ nss_database_check_reload_and_get (struc + && (str.st_ino != local->root_ino + || str.st_dev != local->root_dev))) + { +- /* Change detected; disable reloading. */ ++ /* Change detected; disable reloading and return current state. */ + atomic_store_release (&local->data.reload_disabled, 1); ++ *result = local->data.services[database_index]; + __libc_lock_unlock (local->lock); + __nss_module_disable_loading (); + return true; diff --git a/nss-database-lookup.patch b/nss-database-lookup.patch new file mode 100644 index 0000000..0edc51f --- /dev/null +++ b/nss-database-lookup.patch @@ -0,0 +1,839 @@ +From: DJ Delorie via Libc-alpha +Subject: [PATCH v4] nss: fix nss_database_lookup2's alternate handling [BZ + #27416] +Date: Fri, 05 Mar 2021 20:29:31 -0500 + +__nss_database_lookup2's extra arguments were left unused in the +nsswitch reloading patch set; this broke compat (default config +ignored) and shadow files (secondary name ignored) which relies on +these fallbacks. + +This patch adds in the previous behavior by correcting the +initialization of the database list to reflect the fallbacks. This +means that the nss_database_lookup2 interface no longer needs to be +passed the fallback info, so API and callers were adjusted. + +Since all callers needed to be edited anyway, the calls were changed +from __nss_database_lookup2 to the faster __nss_database_get. This +was an intended optimization which was deferred during the initial +lookup changes to avoid touching so many files. + +The test case verifies that compat targets work (passwd) and that the +default configuration works (group). Tested on x86-64. +--- + nscd/aicache.c | 4 +- + nscd/initgrcache.c | 3 +- + nscd/netgroupcache.c | 2 +- + nss/Makefile | 1 + + nss/Versions | 2 +- + nss/XXX-lookup.c | 17 +--- + nss/databases.def | 3 + + nss/grp-lookup.c | 1 - + nss/hosts-lookup.c | 1 - + nss/key-lookup.c | 1 - + nss/network-lookup.c | 1 - + nss/nss_compat/compat-grp.c | 2 +- + nss/nss_compat/compat-initgroups.c | 2 +- + nss/nss_compat/compat-pwd.c | 2 +- + nss/nss_compat/compat-spwd.c | 3 +- + nss/nss_database.c | 35 ++++++- + nss/nss_database.h | 5 +- + nss/nss_module.c | 20 ++-- + nss/nss_test.h | 7 ++ + nss/nss_test1.c | 93 +++++++++++++++++++ + nss/nsswitch.c | 25 +---- + nss/nsswitch.h | 7 +- + nss/pwd-lookup.c | 1 - + nss/sgrp-lookup.c | 2 - + nss/spwd-lookup.c | 2 - + nss/tst-nss-compat1.c | 81 ++++++++++++++++ + nss/tst-nss-compat1.root/etc/group | 1 + + nss/tst-nss-compat1.root/etc/nsswitch.conf | 3 + + nss/tst-nss-compat1.root/etc/passwd | 3 + + nss/tst-nss-compat1.root/etc/shadow | 2 + + .../tst-nss-compat1.script | 1 + + sysdeps/posix/getaddrinfo.c | 4 +- + 32 files changed, 256 insertions(+), 81 deletions(-) + create mode 100644 nss/tst-nss-compat1.c + create mode 100644 nss/tst-nss-compat1.root/etc/group + create mode 100644 nss/tst-nss-compat1.root/etc/nsswitch.conf + create mode 100644 nss/tst-nss-compat1.root/etc/passwd + create mode 100644 nss/tst-nss-compat1.root/etc/shadow + create mode 100644 nss/tst-nss-compat1.root/tst-nss-compat1.script + +Index: glibc-2.33/nscd/aicache.c +=================================================================== +--- glibc-2.33.orig/nscd/aicache.c ++++ glibc-2.33/nscd/aicache.c +@@ -77,9 +77,7 @@ addhstaiX (struct database_dyn *db, int + int rc4 = 0; + int herrno = 0; + +- no_more = __nss_database_lookup2 ("hosts", NULL, +- "dns [!UNAVAIL=return] files", +- &nip); ++ no_more = (__nss_database_get (nss_database_hosts, &nip) == false); + + /* Initialize configurations. */ + struct resolv_context *ctx = __resolv_context_get (); +Index: glibc-2.33/nscd/initgrcache.c +=================================================================== +--- glibc-2.33.orig/nscd/initgrcache.c ++++ glibc-2.33/nscd/initgrcache.c +@@ -82,8 +82,7 @@ addinitgroupsX (struct database_dyn *db, + int no_more; + + if (group_database == NULL) +- no_more = __nss_database_lookup2 ("group", NULL, "files", +- &group_database); ++ no_more = (__nss_database_get (nss_database_group, &group_database) == false); + else + no_more = 0; + nip = group_database; +Index: glibc-2.33/nscd/netgroupcache.c +=================================================================== +--- glibc-2.33.orig/nscd/netgroupcache.c ++++ glibc-2.33/nscd/netgroupcache.c +@@ -143,7 +143,7 @@ addgetnetgrentX (struct database_dyn *db + *tofreep = NULL; + + if (netgroup_database == NULL +- && __nss_database_lookup2 ("netgroup", NULL, NULL, &netgroup_database)) ++ && !__nss_database_get (nss_database_netgroup, &netgroup_database)) + { + /* No such service. */ + cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, +Index: glibc-2.33/nss/Makefile +=================================================================== +--- glibc-2.33.orig/nss/Makefile ++++ glibc-2.33/nss/Makefile +@@ -63,6 +63,7 @@ tests = test-netdb test-digits-dots ts + xtests = bug-erange + + tests-container = \ ++ tst-nss-compat1 \ + tst-nss-test3 \ + tst-nss-files-hosts-long \ + tst-nss-db-endpwent \ +Index: glibc-2.33/nss/Versions +=================================================================== +--- glibc-2.33.orig/nss/Versions ++++ glibc-2.33/nss/Versions +@@ -17,7 +17,7 @@ libc { + + __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2; + __nss_services_lookup2; __nss_next2; __nss_lookup; +- __nss_hash; __nss_database_lookup2; ++ __nss_hash; __nss_database_lookup2; __nss_database_get; + __nss_files_fopen; __nss_readline; __nss_parse_line_result; + } + } +Index: glibc-2.33/nss/XXX-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/XXX-lookup.c ++++ glibc-2.33/nss/XXX-lookup.c +@@ -37,27 +37,20 @@ + #define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post) + #define CONCAT3_2(Pre, Name, Post) Pre##Name##Post + ++#define DATABASE_NAME_ID CONCAT2_1 (nss_database_, DATABASE_NAME) ++#define CONCAT2_1(Pre, Name) CONCAT2_2 (Pre, Name) ++#define CONCAT2_2(Pre, Name) Pre##Name ++ + #define DATABASE_NAME_SYMBOL CONCAT3_1 (__nss_, DATABASE_NAME, _database) + #define DATABASE_NAME_STRING STRINGIFY1 (DATABASE_NAME) + #define STRINGIFY1(Name) STRINGIFY2 (Name) + #define STRINGIFY2(Name) #Name + +-#ifdef ALTERNATE_NAME +-#define ALTERNATE_NAME_STRING STRINGIFY1 (ALTERNATE_NAME) +-#else +-#define ALTERNATE_NAME_STRING NULL +-#endif +- +-#ifndef DEFAULT_CONFIG +-#define DEFAULT_CONFIG NULL +-#endif +- + int + DB_LOOKUP_FCT (nss_action_list *ni, const char *fct_name, const char *fct2_name, + void **fctp) + { +- if (__nss_database_lookup2 (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING, +- DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0) ++ if (! __nss_database_get (DATABASE_NAME_ID, &DATABASE_NAME_SYMBOL)) + return -1; + + *ni = DATABASE_NAME_SYMBOL; +Index: glibc-2.33/nss/databases.def +=================================================================== +--- glibc-2.33.orig/nss/databases.def ++++ glibc-2.33/nss/databases.def +@@ -23,17 +23,20 @@ + DEFINE_DATABASE (aliases) + DEFINE_DATABASE (ethers) + DEFINE_DATABASE (group) ++DEFINE_DATABASE (group_compat) + DEFINE_DATABASE (gshadow) + DEFINE_DATABASE (hosts) + DEFINE_DATABASE (initgroups) + DEFINE_DATABASE (netgroup) + DEFINE_DATABASE (networks) + DEFINE_DATABASE (passwd) ++DEFINE_DATABASE (passwd_compat) + DEFINE_DATABASE (protocols) + DEFINE_DATABASE (publickey) + DEFINE_DATABASE (rpc) + DEFINE_DATABASE (services) + DEFINE_DATABASE (shadow) ++DEFINE_DATABASE (shadow_compat) + + /* + Local Variables: +Index: glibc-2.33/nss/grp-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/grp-lookup.c ++++ glibc-2.33/nss/grp-lookup.c +@@ -19,6 +19,5 @@ + #include + + #define DATABASE_NAME group +-#define DEFAULT_CONFIG "files" + + #include "XXX-lookup.c" +Index: glibc-2.33/nss/hosts-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/hosts-lookup.c ++++ glibc-2.33/nss/hosts-lookup.c +@@ -17,6 +17,5 @@ + . */ + + #define DATABASE_NAME hosts +-#define DEFAULT_CONFIG "dns [!UNAVAIL=return] files" + + #include "XXX-lookup.c" +Index: glibc-2.33/nss/key-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/key-lookup.c ++++ glibc-2.33/nss/key-lookup.c +@@ -17,6 +17,5 @@ + . */ + + #define DATABASE_NAME publickey +-#define DEFAULT_CONFIG "nis nisplus" + + #include "XXX-lookup.c" +Index: glibc-2.33/nss/network-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/network-lookup.c ++++ glibc-2.33/nss/network-lookup.c +@@ -17,6 +17,5 @@ + . */ + + #define DATABASE_NAME networks +-#define DEFAULT_CONFIG "dns [!UNAVAIL=return] files" + + #include "XXX-lookup.c" +Index: glibc-2.33/nss/nss_compat/compat-grp.c +=================================================================== +--- glibc-2.33.orig/nss/nss_compat/compat-grp.c ++++ glibc-2.33/nss/nss_compat/compat-grp.c +@@ -81,7 +81,7 @@ static bool in_blacklist (const char *, + static void + init_nss_interface (void) + { +- if (__nss_database_lookup2 ("group_compat", NULL, "nis", &ni) >= 0) ++ if (__nss_database_get (nss_database_group_compat, &ni)) + { + setgrent_impl = __nss_lookup_function (ni, "setgrent"); + getgrnam_r_impl = __nss_lookup_function (ni, "getgrnam_r"); +Index: glibc-2.33/nss/nss_compat/compat-initgroups.c +=================================================================== +--- glibc-2.33.orig/nss/nss_compat/compat-initgroups.c ++++ glibc-2.33/nss/nss_compat/compat-initgroups.c +@@ -91,7 +91,7 @@ init_nss_interface (void) + + /* Retest. */ + if (ni == NULL +- && __nss_database_lookup2 ("group_compat", NULL, "nis", &ni) >= 0) ++ && __nss_database_get (nss_database_group_compat, &ni)) + { + initgroups_dyn_impl = __nss_lookup_function (ni, "initgroups_dyn"); + getgrnam_r_impl = __nss_lookup_function (ni, "getgrnam_r"); +Index: glibc-2.33/nss/nss_compat/compat-pwd.c +=================================================================== +--- glibc-2.33.orig/nss/nss_compat/compat-pwd.c ++++ glibc-2.33/nss/nss_compat/compat-pwd.c +@@ -91,7 +91,7 @@ static bool in_blacklist (const char *, + static void + init_nss_interface (void) + { +- if (__nss_database_lookup2 ("passwd_compat", NULL, "nis", &ni) >= 0) ++ if (__nss_database_get (nss_database_passwd_compat, &ni)) + { + setpwent_impl = __nss_lookup_function (ni, "setpwent"); + getpwnam_r_impl = __nss_lookup_function (ni, "getpwnam_r"); +Index: glibc-2.33/nss/nss_compat/compat-spwd.c +=================================================================== +--- glibc-2.33.orig/nss/nss_compat/compat-spwd.c ++++ glibc-2.33/nss/nss_compat/compat-spwd.c +@@ -88,8 +88,7 @@ static bool in_blacklist (const char *, + static void + init_nss_interface (void) + { +- if (__nss_database_lookup2 ("shadow_compat", "passwd_compat", +- "nis", &ni) >= 0) ++ if (__nss_database_get (nss_database_shadow_compat, &ni)) + { + setspent_impl = __nss_lookup_function (ni, "setspent"); + getspnam_r_impl = __nss_lookup_function (ni, "getspnam_r"); +Index: glibc-2.33/nss/nss_database.c +=================================================================== +--- glibc-2.33.orig/nss/nss_database.c ++++ glibc-2.33/nss/nss_database.c +@@ -93,13 +93,16 @@ enum nss_database_default + static const char per_database_defaults[NSS_DATABASE_COUNT] = + { + [nss_database_group] = nss_database_default_compat, ++ [nss_database_group_compat] = nss_database_default_nis, + [nss_database_gshadow] = nss_database_default_files, + [nss_database_hosts] = nss_database_default_dns, + [nss_database_initgroups] = nss_database_default_none, + [nss_database_networks] = nss_database_default_dns, + [nss_database_passwd] = nss_database_default_compat, ++ [nss_database_passwd_compat] = nss_database_default_nis, + [nss_database_publickey] = nss_database_default_nis_nisplus, + [nss_database_shadow] = nss_database_default_compat, ++ [nss_database_shadow_compat] = nss_database_default_nis, + }; + + struct nss_database_default_cache +@@ -166,13 +169,12 @@ nss_database_select_default (struct nss_ + assert (errno == ENOMEM); + return false; + } +- else +- return true; ++ return true; + } + + /* database_name must be large enough for each individual name plus a + null terminator. */ +-typedef char database_name[11]; ++typedef char database_name[14]; + #define DEFINE_DATABASE(name) \ + _Static_assert (sizeof (#name) <= sizeof (database_name), #name); + #include "databases.def" +@@ -325,14 +327,40 @@ nss_database_reload (struct nss_database + /* No other threads have access to fp. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + ++ /* We start with all of *staging pointing to NULL. */ ++ + bool ok = true; + if (fp != NULL) + ok = nss_database_reload_1 (staging, fp); + ++ /* Now we have non-NULL entries where the user explictly listed the ++ service in nsswitch.conf. */ ++ + /* Apply defaults. */ + if (ok) + { + struct nss_database_default_cache cache = { }; ++ ++ /* These three default to other services if the user listed the ++ other service. */ ++ ++ /* was lookup2() in nss/nss_compat/compat-spwd.c */ ++ if (staging->services[nss_database_shadow_compat] == NULL) ++ staging->services[nss_database_shadow_compat] = ++ staging->services[nss_database_passwd_compat]; ++ ++ /* was ALTERNATE_NAME in nss/spwd_lookup.c */ ++ if (staging->services[nss_database_shadow] == NULL) ++ staging->services[nss_database_shadow] = ++ staging->services[nss_database_passwd]; ++ ++ /* was ALTERNATE_NAME in nss/sgrp_lookup.c */ ++ if (staging->services[nss_database_gshadow] == NULL) ++ staging->services[nss_database_gshadow] = ++ staging->services[nss_database_group]; ++ ++ /* For anything still unspecified, load the default configs. */ ++ + for (int i = 0; i < NSS_DATABASE_COUNT; ++i) + if (staging->services[i] == NULL) + { +@@ -442,6 +470,7 @@ __nss_database_get (enum nss_database db + struct nss_database_state *local = nss_database_state_get (); + return nss_database_check_reload_and_get (local, actions, db); + } ++libc_hidden_def (__nss_database_get) + + nss_action_list + __nss_database_get_noreload (enum nss_database db) +Index: glibc-2.33/nss/nss_database.h +=================================================================== +--- glibc-2.33.orig/nss/nss_database.h ++++ glibc-2.33/nss/nss_database.h +@@ -52,12 +52,11 @@ enum nss_database + NSS_DATABASE_COUNT + }; + +- + /* Looks up the action list for DB and stores it in *ACTIONS. Returns + true on success or false on failure. Success can mean that + *ACTIONS is NULL. */ +-bool __nss_database_get (enum nss_database db, nss_action_list *actions) +- attribute_hidden; ++bool __nss_database_get (enum nss_database db, nss_action_list *actions); ++libc_hidden_proto (__nss_database_get) + + /* Like __nss_database_get, but does not reload /etc/nsswitch.conf + from disk. This assumes that there has been a previous successful +Index: glibc-2.33/nss/nss_module.c +=================================================================== +--- glibc-2.33.orig/nss/nss_module.c ++++ glibc-2.33/nss/nss_module.c +@@ -31,14 +31,6 @@ + #include + #include + +-#ifdef LINK_OBSOLETE_NSL +-# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" +-# define DEFAULT_DEFCONFIG "nis [NOTFOUND=return] files" +-#else +-# define DEFAULT_CONFIG "files" +-# define DEFAULT_DEFCONFIG "files" +-#endif +- + /* Suffix after .so of NSS service modules. This is a bit of magic, + but we assume LIBNSS_FILES_SO looks like "libnss_files.so.2" and we + want a pointer to the ".2" part. We have no API to extract this +@@ -292,11 +284,11 @@ __nss_module_get_function (struct nss_mo + #if defined SHARED && defined USE_NSCD + /* Load all libraries for the service. */ + static void +-nss_load_all_libraries (const char *service, const char *def) ++nss_load_all_libraries (enum nss_database service) + { + nss_action_list ni = NULL; + +- if (__nss_database_lookup2 (service, NULL, def, &ni) == 0) ++ if (__nss_database_get (service, &ni)) + while (ni->module != NULL) + { + __nss_module_load (ni->module); +@@ -323,10 +315,10 @@ __nss_disable_nscd (void (*cb) (size_t, + is_nscd = true; + + /* Find all the relevant modules so that the init functions are called. */ +- nss_load_all_libraries ("passwd", DEFAULT_CONFIG); +- nss_load_all_libraries ("group", DEFAULT_CONFIG); +- nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files"); +- nss_load_all_libraries ("services", NULL); ++ nss_load_all_libraries (nss_database_passwd); ++ nss_load_all_libraries (nss_database_group); ++ nss_load_all_libraries (nss_database_hosts); ++ nss_load_all_libraries (nss_database_services); + + /* Make sure NSCD purges its cache if nsswitch.conf changes. */ + init_traced_file (&pwd_traced_file.file, _PATH_NSSWITCH_CONF, 0); +Index: glibc-2.33/nss/nss_test.h +=================================================================== +--- glibc-2.33.orig/nss/nss_test.h ++++ glibc-2.33/nss/nss_test.h +@@ -33,11 +33,13 @@ + + #include + #include ++#include + #include + + typedef struct test_tables { + struct passwd *pwd_table; + struct group *grp_table; ++ struct spwd *spwd_table; + struct hostent *host_table; + } test_tables; + +@@ -46,10 +48,12 @@ extern void _nss_test2_init_hook (test_t + + #define PWD_LAST() { .pw_name = NULL, .pw_uid = 0 } + #define GRP_LAST() { .gr_name = NULL, .gr_gid = 0 } ++#define SPWD_LAST() { .sp_namp = NULL, .sp_pwdp = NULL } + #define HOST_LAST() { .h_name = NULL, .h_aliases = NULL, .h_length = 0, .h_addr_list = NULL } + + #define PWD_ISLAST(p) ((p)->pw_name == NULL && (p)->pw_uid == 0) + #define GRP_ISLAST(g) ((g)->gr_name == NULL && (g)->gr_gid == 0) ++#define SPWD_ISLAST(s) ((s)->sp_namp == NULL && (s)->sp_pwdp == 0) + #define HOST_ISLAST(h) ((h)->h_name == NULL && (h)->h_length == 0) + + /* Macros to fill in the tables easily. */ +@@ -76,6 +80,9 @@ extern void _nss_test2_init_hook (test_t + { .gr_name = (char *) n, .gr_passwd = (char *) "*", .gr_gid = u, \ + .gr_mem = (char **) m } + ++#define SPWD(u) \ ++ { .sp_namp = (char *) "name" #u, .sp_pwdp = (char *) "passwd" #u } ++ + #define HOST(u) \ + { .h_name = (char *) "name" #u, .h_aliases = NULL, .h_addrtype = u, \ + .h_length = 4, \ +Index: glibc-2.33/nss/nss_test1.c +=================================================================== +--- glibc-2.33.orig/nss/nss_test1.c ++++ glibc-2.33/nss/nss_test1.c +@@ -66,6 +66,9 @@ static int npwd_data = default_npwd_data + static struct group *grp_data = NULL; + static int ngrp_data = 0; + ++static struct spwd *spwd_data = NULL; ++static int nspwd_data = 0; ++ + static struct hostent *host_data = NULL; + static int nhost_data = 0; + +@@ -102,6 +105,13 @@ init(void) + ; + ngrp_data = i; + } ++ if (t.spwd_table) ++ { ++ spwd_data = t.spwd_table; ++ for (i=0; ! SPWD_ISLAST(& spwd_data[i]); i++) ++ ; ++ nspwd_data = i; ++ } + if (t.host_table) + { + host_data = t.host_table; +@@ -322,6 +332,89 @@ NAME(getgrnam_r) (const char *name, stru + + return NSS_STATUS_NOTFOUND; + } ++ ++/* -------------------------------------------------- */ ++/* Shadow password handling. */ ++ ++static size_t spwd_iter; ++#define CURSPWD spwd_data[spwd_iter] ++ ++static pthread_mutex_t spwd_lock = PTHREAD_MUTEX_INITIALIZER; ++ ++enum nss_status ++NAME(setspent) (int stayopen) ++{ ++ init(); ++ spwd_iter = 0; ++ return NSS_STATUS_SUCCESS; ++} ++ ++ ++enum nss_status ++NAME(endspwent) (void) ++{ ++ init(); ++ return NSS_STATUS_SUCCESS; ++} ++ ++static enum nss_status ++copy_shadow (struct spwd *result, struct spwd *local, ++ char *buffer, size_t buflen, int *errnop) ++{ ++ struct alloc_buffer buf = alloc_buffer_create (buffer, buflen); ++ ++ result->sp_namp = alloc_buffer_maybe_copy_string (&buf, local->sp_namp); ++ result->sp_pwdp = alloc_buffer_maybe_copy_string (&buf, local->sp_pwdp); ++ result->sp_lstchg = local->sp_lstchg; ++ result->sp_min = local->sp_min; ++ result->sp_max = local->sp_max; ++ result->sp_warn = local->sp_warn; ++ result->sp_inact = local->sp_inact; ++ result->sp_expire = local->sp_expire; ++ result->sp_flag = local->sp_flag; ++ ++ if (alloc_buffer_has_failed (&buf)) ++ { ++ *errnop = ERANGE; ++ return NSS_STATUS_TRYAGAIN; ++ } ++ ++ return NSS_STATUS_SUCCESS; ++} ++ ++enum nss_status ++NAME(getspent_r) (struct spwd *result, char *buffer, size_t buflen, ++ int *errnop) ++{ ++ int res = NSS_STATUS_SUCCESS; ++ ++ init(); ++ pthread_mutex_lock (&spwd_lock); ++ ++ if (spwd_iter >= nspwd_data) ++ res = NSS_STATUS_NOTFOUND; ++ else ++ { ++ res = copy_shadow (result, &CURSPWD, buffer, buflen, errnop); ++ ++spwd_iter; ++ } ++ ++ pthread_mutex_unlock (&spwd_lock); ++ ++ return res; ++} ++ ++enum nss_status ++NAME(getspnam_r) (const char *name, struct spwd *result, char *buffer, ++ size_t buflen, int *errnop) ++{ ++ init(); ++ for (size_t idx = 0; idx < nspwd_data; ++idx) ++ if (strcmp (spwd_data[idx].sp_namp, name) == 0) ++ return copy_shadow (result, &spwd_data[idx], buffer, buflen, errnop); ++ ++ return NSS_STATUS_NOTFOUND; ++} + + /* -------------------------------------------------- */ + /* Host handling. */ +Index: glibc-2.33/nss/nsswitch.c +=================================================================== +--- glibc-2.33.orig/nss/nsswitch.c ++++ glibc-2.33/nss/nsswitch.c +@@ -63,37 +63,22 @@ static const char * database_names[] = { + bool __nss_database_custom[NSS_DBSIDX_max]; + #endif + +- + /*__libc_lock_define_initialized (static, lock)*/ + + /* -1 == database not found + 0 == database entry pointer stored */ + int +-__nss_database_lookup2 (const char *database, const char *alternate_name, +- const char *defconfig, nss_action_list *ni) ++__nss_database_lookup2 (const char *database, nss_action_list *ni) + { + int database_id; + + for (database_id = 0; database_names[database_id]; database_id++) + if (strcmp (database_names[database_id], database) == 0) +- break; +- +- if (database_names[database_id] == NULL) +- return -1; ++ if (__nss_database_get (database_id, ni)) ++ return 0; + +- /* If *NI is NULL, the database was not mentioned in nsswitch.conf. +- If *NI is not NULL, but *NI->module is NULL, the database was in +- nsswitch.conf but listed no actions. We test for the former. */ +- if (__nss_database_get (database_id, ni) && *ni != NULL) +- { +- /* Success. */ +- return 0; +- } +- else +- { +- /* Failure. */ +- return -1; +- } ++ /* Failure. */ ++ return -1; + } + libc_hidden_def (__nss_database_lookup2) + +Index: glibc-2.33/nss/nsswitch.h +=================================================================== +--- glibc-2.33.orig/nss/nsswitch.h ++++ glibc-2.33/nss/nsswitch.h +@@ -88,13 +88,10 @@ extern bool __nss_database_custom[NSS_DB + + /* Interface functions for NSS. */ + +-/* Get the data structure representing the specified database. +- If there is no configuration for this database in the file, +- parse a service list from DEFCONFIG and use that. More ++/* Get the data structure representing the specified database. More + than one function can use the database. */ + extern int __nss_database_lookup2 (const char *database, +- const char *alternative_name, +- const char *defconfig, struct nss_action **ni); ++ struct nss_action **ni); + libc_hidden_proto (__nss_database_lookup2) + + /* Put first function with name FCT_NAME for SERVICE in FCTP. The +Index: glibc-2.33/nss/pwd-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/pwd-lookup.c ++++ glibc-2.33/nss/pwd-lookup.c +@@ -19,6 +19,5 @@ + #include + + #define DATABASE_NAME passwd +-#define DEFAULT_CONFIG "files" + + #include "XXX-lookup.c" +Index: glibc-2.33/nss/sgrp-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/sgrp-lookup.c ++++ glibc-2.33/nss/sgrp-lookup.c +@@ -17,7 +17,5 @@ + . */ + + #define DATABASE_NAME gshadow +-#define ALTERNATE_NAME group +-#define DEFAULT_CONFIG "files" + + #include "XXX-lookup.c" +Index: glibc-2.33/nss/spwd-lookup.c +=================================================================== +--- glibc-2.33.orig/nss/spwd-lookup.c ++++ glibc-2.33/nss/spwd-lookup.c +@@ -19,7 +19,5 @@ + #include + + #define DATABASE_NAME shadow +-#define ALTERNATE_NAME passwd +-#define DEFAULT_CONFIG "files" + + #include "XXX-lookup.c" +Index: glibc-2.33/nss/tst-nss-compat1.c +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-nss-compat1.c +@@ -0,0 +1,81 @@ ++/* Test error checking for group entries. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#include "nss_test.h" ++ ++static struct passwd pwd_table[] = { ++ PWD (100), ++ PWD (30), ++ PWD_LAST () ++ }; ++ ++static struct spwd spwd_table[] = { ++ SPWD (100), ++ SPWD (30), ++ SPWD_LAST () ++ }; ++ ++void ++_nss_test1_init_hook(test_tables *t) ++{ ++ t->pwd_table = pwd_table; ++ t->spwd_table = spwd_table; ++} ++ ++static int ++do_test (void) ++{ ++ struct passwd *p = NULL; ++ struct spwd *s = NULL; ++ struct group *g = NULL; ++ ++ /* Test that compat-to-test works. */ ++ p = getpwuid (100); ++ if (p == NULL) ++ FAIL_EXIT1("getpwuid-compat-test1 p"); ++ else if (strcmp (p->pw_name, "name100") != 0) ++ FAIL_EXIT1("getpwuid-compat-test1 name100"); ++ ++ /* Shadow compat should use passwd via the alternate name. */ ++ s = getspnam ("name30"); ++ if (s == NULL) ++ FAIL_EXIT1("getspnam-compat-test1 s"); ++ else if (strcmp (s->sp_namp, "name30") != 0) ++ FAIL_EXIT1("getpwuid-compat-test1 name30"); ++ ++ /* Test that internal defconfig works. */ ++ g = getgrgid (100); ++ if (g == NULL) ++ FAIL_EXIT1("getgrgid-compat-null"); ++ if (strcmp (g->gr_name, "wilma") != 0) ++ FAIL_EXIT1("getgrgid-compat-name"); ++ ++ return 0; ++} ++ ++#include +Index: glibc-2.33/nss/tst-nss-compat1.root/etc/group +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-nss-compat1.root/etc/group +@@ -0,0 +1 @@ ++wilma:x:100: +Index: glibc-2.33/nss/tst-nss-compat1.root/etc/nsswitch.conf +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-nss-compat1.root/etc/nsswitch.conf +@@ -0,0 +1,3 @@ ++passwd : compat ++passwd_compat : test1 ++ +Index: glibc-2.33/nss/tst-nss-compat1.root/etc/passwd +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-nss-compat1.root/etc/passwd +@@ -0,0 +1,3 @@ ++name5:x:5:555:name5 for testing:/home/name5:/bin/nologin +++name100 +++name30 +Index: glibc-2.33/nss/tst-nss-compat1.root/etc/shadow +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-nss-compat1.root/etc/shadow +@@ -0,0 +1,2 @@ +++name100 +++name30 +Index: glibc-2.33/nss/tst-nss-compat1.root/tst-nss-compat1.script +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-nss-compat1.root/tst-nss-compat1.script +@@ -0,0 +1 @@ ++cp $B/nss/libnss_test1.so $L/libnss_test1.so.2 +Index: glibc-2.33/sysdeps/posix/getaddrinfo.c +=================================================================== +--- glibc-2.33.orig/sysdeps/posix/getaddrinfo.c ++++ glibc-2.33/sysdeps/posix/getaddrinfo.c +@@ -720,9 +720,7 @@ gaih_inet (const char *name, const struc + } + #endif + +- no_more = __nss_database_lookup2 ("hosts", NULL, +- "dns [!UNAVAIL=return] files", +- &nip); ++ no_more = (__nss_database_get (nss_database_hosts, &nip) == false); + + /* If we are looking for both IPv4 and IPv6 address we don't + want the lookup functions to automatically promote IPv4 diff --git a/nss-load-chroot.patch b/nss-load-chroot.patch new file mode 100644 index 0000000..e9a5d3e --- /dev/null +++ b/nss-load-chroot.patch @@ -0,0 +1,172 @@ +From 3e880d733753183696d1a81c34caef3a9add2b0c Mon Sep 17 00:00:00 2001 +From: DJ Delorie +Date: Thu, 18 Feb 2021 15:26:30 -0500 +Subject: [PATCH] nss: Re-enable NSS module loading after chroot [BZ #27389] + +The glibc 2.33 release enabled /etc/nsswitch.conf reloading, +and to prevent potential security issues like CVE-2019-14271 +the re-loading of nsswitch.conf and all mdoules was disabled +when the root filesystem changes (see bug 27077). + +Unfortunately php-lpfm and openldap both require the ability +to continue to load NSS modules after chroot. The packages +do not exec after the chroot, and so do not cause the +protections to be reset. The only solution is to re-enable +only NSS module loading (not nsswitch.conf reloading) and so +get back the previous glibc behaviour. + +In the future we may introduce a way to harden applications +so they do not reload NSS modules once the root filesystem +changes, or that only files/dns are available pre-loaded +(or builtin). + +Reviewed-by: Carlos O'Donell +(cherry picked from commit 58673149f37389495c098421085ffdb468b3f7ad) +--- + nss/nss_database.c | 1 - + nss/tst-reload2.c | 35 +++++++++++++++---- + nss/tst-reload2.root/etc/hosts | 1 + + nss/tst-reload2.root/etc/nsswitch.conf | 1 + + nss/tst-reload2.root/subdir/etc/hosts | 1 + + nss/tst-reload2.root/subdir/etc/nsswitch.conf | 1 + + 6 files changed, 32 insertions(+), 8 deletions(-) + create mode 100644 nss/tst-reload2.root/etc/hosts + create mode 100644 nss/tst-reload2.root/subdir/etc/hosts + +Index: glibc-2.33/nss/nss_database.c +=================================================================== +--- glibc-2.33.orig/nss/nss_database.c ++++ glibc-2.33/nss/nss_database.c +@@ -404,7 +404,6 @@ nss_database_check_reload_and_get (struc + atomic_store_release (&local->data.reload_disabled, 1); + *result = local->data.services[database_index]; + __libc_lock_unlock (local->lock); +- __nss_module_disable_loading (); + return true; + } + local->root_ino = str.st_ino; +Index: glibc-2.33/nss/tst-reload2.c +=================================================================== +--- glibc-2.33.orig/nss/tst-reload2.c ++++ glibc-2.33/nss/tst-reload2.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -48,7 +49,7 @@ static const char *group_4[] = { + "alpha", "beta", "gamma", "fred", NULL + }; + +-static struct group group_table_data[] = ++static struct group group_table_data1[] = + { + GRP (4), + GRP_LAST () +@@ -58,7 +59,7 @@ void + _nss_test1_init_hook (test_tables *t) + { + t->pwd_table = pwd_table1; +- t->grp_table = group_table_data; ++ t->grp_table = group_table_data1; + } + + static struct passwd pwd_table2[] = +@@ -68,10 +69,21 @@ static struct passwd pwd_table2[] = + PWD_LAST () + }; + ++static const char *group_5[] = { ++ "fred", NULL ++}; ++ ++static struct group group_table_data2[] = ++ { ++ GRP (5), ++ GRP_LAST () ++ }; ++ + void + _nss_test2_init_hook (test_tables *t) + { + t->pwd_table = pwd_table2; ++ t->grp_table = group_table_data2; + } + + static int +@@ -79,6 +91,7 @@ do_test (void) + { + struct passwd *pw; + struct group *gr; ++ struct hostent *he; + char buf1[PATH_MAX]; + char buf2[PATH_MAX]; + +@@ -99,7 +112,9 @@ do_test (void) + TEST_COMPARE (pw->pw_uid, 1234); + + /* This just loads the test2 DSO. */ +- gr = getgrnam ("name4"); ++ gr = getgrgid (5); ++ TEST_VERIFY (gr != NULL); ++ + + /* Change the root dir. */ + +@@ -114,15 +129,21 @@ do_test (void) + if (pw) + TEST_VERIFY (pw->pw_uid != 2468); + +- /* The "files" DSO should not be loaded. */ +- gr = getgrnam ("test3"); +- TEST_VERIFY (gr == NULL); +- + /* We should still be using the old configuration. */ + pw = getpwnam ("test1"); + TEST_VERIFY (pw != NULL); + if (pw) + TEST_COMPARE (pw->pw_uid, 1234); ++ gr = getgrgid (5); ++ TEST_VERIFY (gr != NULL); ++ gr = getgrnam ("name4"); ++ TEST_VERIFY (gr == NULL); ++ ++ /* hosts in the outer nsswitch is files; the inner one is test1. ++ Verify that we're still using the outer nsswitch *and* that we ++ can load the files DSO. */ ++ he = gethostbyname ("test2"); ++ TEST_VERIFY (he != NULL); + + return 0; + } +Index: glibc-2.33/nss/tst-reload2.root/etc/hosts +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-reload2.root/etc/hosts +@@ -0,0 +1 @@ ++1.2.3.4 test1 +Index: glibc-2.33/nss/tst-reload2.root/etc/nsswitch.conf +=================================================================== +--- glibc-2.33.orig/nss/tst-reload2.root/etc/nsswitch.conf ++++ glibc-2.33/nss/tst-reload2.root/etc/nsswitch.conf +@@ -1,2 +1,3 @@ + passwd: test1 + group: test2 ++hosts: files +Index: glibc-2.33/nss/tst-reload2.root/subdir/etc/hosts +=================================================================== +--- /dev/null ++++ glibc-2.33/nss/tst-reload2.root/subdir/etc/hosts +@@ -0,0 +1 @@ ++1.2.3.4 test2 +Index: glibc-2.33/nss/tst-reload2.root/subdir/etc/nsswitch.conf +=================================================================== +--- glibc-2.33.orig/nss/tst-reload2.root/subdir/etc/nsswitch.conf ++++ glibc-2.33/nss/tst-reload2.root/subdir/etc/nsswitch.conf +@@ -1,2 +1,3 @@ + passwd: test2 + group: files ++hosts: test1 diff --git a/nss-revert-api.patch b/nss-revert-api.patch deleted file mode 100644 index eb9a8f9..0000000 --- a/nss-revert-api.patch +++ /dev/null @@ -1,4609 +0,0 @@ -Index: glibc-2.33/grp/Makefile -=================================================================== ---- glibc-2.33.orig/grp/Makefile -+++ glibc-2.33/grp/Makefile -@@ -31,10 +31,6 @@ routines := fgetgrent initgroups setgrou - - tests := testgrp tst-putgrent - --tests-container = \ -- tst-initgroups1 \ -- tst-initgroups2 -- - ifeq (yes,$(build-shared)) - test-srcs := tst_fgetgrent - ifeq ($(run-built-tests),yes) -Index: glibc-2.33/grp/compat-initgroups.c -=================================================================== ---- glibc-2.33.orig/grp/compat-initgroups.c -+++ glibc-2.33/grp/compat-initgroups.c -@@ -10,7 +10,7 @@ typedef enum nss_status (*get_function) - - - static enum nss_status --compat_call (nss_action_list nip, const char *user, gid_t group, long int *start, -+compat_call (service_user *nip, const char *user, gid_t group, long int *start, - long int *size, gid_t **groupsp, long int limit, int *errnop) - { - struct group grpbuf; -Index: glibc-2.33/grp/initgroups.c -=================================================================== ---- glibc-2.33.orig/grp/initgroups.c -+++ glibc-2.33/grp/initgroups.c -@@ -63,6 +63,7 @@ internal_getgrouplist (const char *user, - #endif - - enum nss_status status = NSS_STATUS_UNAVAIL; -+ int no_more = 0; - - /* Never store more than the starting *SIZE number of elements. */ - assert (*size > 0); -@@ -70,25 +71,28 @@ internal_getgrouplist (const char *user, - /* Start is one, because we have the first group as parameter. */ - long int start = 1; - -- nss_action_list nip; -- -- if (__nss_database_get (nss_database_initgroups, &nip) -- && nip != NULL) -- { -- use_initgroups_entry = true; -- } -- else if (__nss_database_get (nss_database_group, &nip) -- && nip != NULL) -+ if (__nss_initgroups_database == NULL) - { -- use_initgroups_entry = false; -+ if (__nss_database_lookup2 ("initgroups", NULL, "", -+ &__nss_initgroups_database) < 0) -+ { -+ if (__nss_group_database == NULL) -+ no_more = __nss_database_lookup2 ("group", NULL, "files", -+ &__nss_group_database); -+ -+ __nss_initgroups_database = __nss_group_database; -+ } -+ else -+ use_initgroups_entry = true; - } - else -- { -- nip = __nss_action_parse ("files"); -- use_initgroups_entry = false; -- } -+ /* __nss_initgroups_database might have been set through -+ __nss_configure_lookup in which case use_initgroups_entry was -+ not set here. */ -+ use_initgroups_entry = __nss_initgroups_database != __nss_group_database; - -- while (nip && nip->module) -+ service_user *nip = __nss_initgroups_database; -+ while (! no_more) - { - long int prev_start = start; - -@@ -130,7 +134,10 @@ internal_getgrouplist (const char *user, - && nss_next_action (nip, status) == NSS_ACTION_RETURN) - break; - -- nip++; -+ if (nip->next == NULL) -+ no_more = -1; -+ else -+ nip = nip->next; - } - - return start; -Index: glibc-2.33/grp/tst-initgroups1.c -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups1.c -+++ /dev/null -@@ -1,56 +0,0 @@ --/* Test that initgroups works. -- Copyright (C) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include -- --/* Test that initgroups includes secondary groups. -- https://bugzilla.redhat.com/show_bug.cgi?id=1906066 */ -- --/* This version uses the wrapper around the groups module. */ -- --#define EXPECTED_N_GROUPS 4 --static gid_t expected_groups[] = -- { 20, 30, 50, 51 }; -- --static int --do_test (void) --{ -- gid_t mygroups [50]; -- int i, n; -- -- n = 50; -- getgrouplist ("dj", 20, mygroups, &n); -- -- TEST_COMPARE (n, EXPECTED_N_GROUPS); -- for (i=0; i -Index: glibc-2.33/grp/tst-initgroups1.root/etc/group -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups1.root/etc/group -+++ /dev/null -@@ -1,7 +0,0 @@ --abc:x:10: --def:x:20: --ghi:x:30:dj --jkl:x:40: --m:x:50:not,dj --n:x:51:dj,not --np:x:60:djx -Index: glibc-2.33/grp/tst-initgroups1.root/etc/nsswitch.conf -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups1.root/etc/nsswitch.conf -+++ /dev/null -@@ -1 +0,0 @@ --group : files -Index: glibc-2.33/grp/tst-initgroups1.root/etc/passwd -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups1.root/etc/passwd -+++ /dev/null -@@ -1 +0,0 @@ --dj:x:84:20:DJ:/:/bin/sh -Index: glibc-2.33/grp/tst-initgroups2.c -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups2.c -+++ /dev/null -@@ -1,21 +0,0 @@ --/* Test that initgroups works. -- Copyright (C) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include "tst-initgroups1.c" -- --/* This version uses the initgroups built in to the files module. */ -Index: glibc-2.33/grp/tst-initgroups2.root/etc/group -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups2.root/etc/group -+++ /dev/null -@@ -1,7 +0,0 @@ --abc:x:10: --def:x:20: --ghi:x:30:dj --jkl:x:40: --m:x:50:not,dj --n:x:51:dj,not --np:x:60:djx -Index: glibc-2.33/grp/tst-initgroups2.root/etc/nsswitch.conf -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups2.root/etc/nsswitch.conf -+++ /dev/null -@@ -1,2 +0,0 @@ --initgroups : files --group : notfiles -Index: glibc-2.33/grp/tst-initgroups2.root/etc/passwd -=================================================================== ---- glibc-2.33.orig/grp/tst-initgroups2.root/etc/passwd -+++ /dev/null -@@ -1 +0,0 @@ --dj:x:84:20:DJ:/:/bin/sh -Index: glibc-2.33/inet/ether_hton.c -=================================================================== ---- glibc-2.33.orig/inet/ether_hton.c -+++ glibc-2.33/inet/ether_hton.c -@@ -30,7 +30,9 @@ typedef int (*lookup_function) (const ch - int - ether_hostton (const char *hostname, struct ether_addr *addr) - { -- nss_action_list nip; -+ static service_user *startp; -+ static lookup_function start_fct; -+ service_user *nip; - union - { - lookup_function f; -@@ -40,7 +42,22 @@ ether_hostton (const char *hostname, str - enum nss_status status = NSS_STATUS_UNAVAIL; - struct etherent etherent; - -- no_more = __nss_ethers_lookup2 (&nip, "gethostton_r", NULL, &fct.ptr); -+ if (startp == NULL) -+ { -+ no_more = __nss_ethers_lookup2 (&nip, "gethostton_r", NULL, &fct.ptr); -+ if (no_more) -+ startp = (service_user *) -1; -+ else -+ { -+ startp = nip; -+ start_fct = fct.f; -+ } -+ } -+ else -+ { -+ fct.f = start_fct; -+ no_more = (nip = startp) == (service_user *) -1; -+ } - - while (no_more == 0) - { -Index: glibc-2.33/inet/ether_ntoh.c -=================================================================== ---- glibc-2.33.orig/inet/ether_ntoh.c -+++ glibc-2.33/inet/ether_ntoh.c -@@ -31,7 +31,9 @@ typedef int (*lookup_function) (const st - int - ether_ntohost (char *hostname, const struct ether_addr *addr) - { -- nss_action_list nip; -+ static service_user *startp; -+ static lookup_function start_fct; -+ service_user *nip; - union - { - lookup_function f; -@@ -41,7 +43,22 @@ ether_ntohost (char *hostname, const str - enum nss_status status = NSS_STATUS_UNAVAIL; - struct etherent etherent; - -- no_more = __nss_ethers_lookup2 (&nip, "getntohost_r", NULL, &fct.ptr); -+ if (startp == NULL) -+ { -+ no_more = __nss_ethers_lookup2 (&nip, "getntohost_r", NULL, &fct.ptr); -+ if (no_more) -+ startp = (service_user *) -1; -+ else -+ { -+ startp = nip; -+ start_fct = fct.f; -+ } -+ } -+ else -+ { -+ fct.f = start_fct; -+ no_more = (nip = startp) == (service_user *) -1; -+ } - - while (no_more == 0) - { -Index: glibc-2.33/inet/getnetgrent_r.c -=================================================================== ---- glibc-2.33.orig/inet/getnetgrent_r.c -+++ glibc-2.33/inet/getnetgrent_r.c -@@ -39,12 +39,40 @@ static struct __netgrent dataset; - /* Set up NIP to run through the services. Return nonzero if there are no - services (left). */ - static int --setup (void **fctp, nss_action_list *nipp) -+setup (void **fctp, service_user **nipp) - { -+ /* Remember the first service_entry, it's always the same. */ -+ static bool startp_initialized; -+ static service_user *startp; - int no_more; - -- no_more = __nss_netgroup_lookup2 (nipp, "setnetgrent", NULL, fctp); -- -+ if (!startp_initialized) -+ { -+ /* Executing this more than once at the same time must yield the -+ same result every time. So we need no locking. */ -+ no_more = __nss_netgroup_lookup2 (nipp, "setnetgrent", NULL, fctp); -+ startp = no_more ? (service_user *) -1 : *nipp; -+#ifdef PTR_MANGLE -+ PTR_MANGLE (startp); -+#endif -+ atomic_write_barrier (); -+ startp_initialized = true; -+ } -+ else -+ { -+ service_user *nip = startp; -+#ifdef PTR_DEMANGLE -+ PTR_DEMANGLE (nip); -+#endif -+ if (nip == (service_user *) -1) -+ /* No services at all. */ -+ return 1; -+ -+ /* Reset to the beginning of the service list. */ -+ *nipp = nip; -+ /* Look up the first function. */ -+ no_more = __nss_lookup (nipp, "setnetgrent", NULL, fctp); -+ } - return no_more; - } - -@@ -72,7 +100,7 @@ endnetgrent_hook (struct __netgrent *dat - { - enum nss_status (*endfct) (struct __netgrent *); - -- if (datap->nip == NULL || datap->nip == (nss_action_list) -1l) -+ if (datap->nip == NULL || datap->nip == (service_user *) -1l) - return; - - endfct = __nss_lookup_function (datap->nip, "endnetgrent"); -@@ -105,7 +133,7 @@ __internal_setnetgrent_reuse (const char - /* Ignore status, we force check in `__nss_next2'. */ - status = DL_CALL_FCT (*fct.f, (group, datap)); - -- nss_action_list old_nip = datap->nip; -+ service_user *old_nip = datap->nip; - no_more = __nss_next2 (&datap->nip, "setnetgrent", NULL, &fct.ptr, - status, 0); - -@@ -247,7 +275,7 @@ __internal_getnetgrent_r (char **hostp, - /* This bogus function pointer is a special marker left by - __nscd_setnetgrent to tell us to use the data it left - before considering any modules. */ -- if (datap->nip == (nss_action_list) -1l) -+ if (datap->nip == (service_user *) -1l) - fct = nscd_getnetgrent; - else - #endif -Index: glibc-2.33/inet/netgroup.h -=================================================================== ---- glibc-2.33.orig/inet/netgroup.h -+++ glibc-2.33/inet/netgroup.h -@@ -64,7 +64,7 @@ struct __netgrent - - /* This handle for the NSS data base is shared between all - set/get/endXXXent functions. */ -- struct nss_action *nip; -+ service_user *nip; - }; - - -Index: glibc-2.33/malloc/set-freeres.c -=================================================================== ---- glibc-2.33.orig/malloc/set-freeres.c -+++ glibc-2.33/malloc/set-freeres.c -@@ -20,7 +20,6 @@ - #include - #include - --#include "../nss/nsswitch.h" - #include "../libio/libioP.h" - - DEFINE_HOOK (__libc_subfreeres, (void)); -@@ -42,10 +41,6 @@ __libc_freeres (void) - { - void *const *p; - -- call_function_static_weak (__nss_module_freeres); -- call_function_static_weak (__nss_action_freeres); -- call_function_static_weak (__nss_database_freeres); -- - _IO_cleanup (); - - /* We run the resource freeing after IO cleanup. */ -Index: glibc-2.33/nscd/aicache.c -=================================================================== ---- glibc-2.33.orig/nscd/aicache.c -+++ glibc-2.33/nscd/aicache.c -@@ -71,15 +71,20 @@ addhstaiX (struct database_dyn *db, int - dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) key); - } - -- nss_action_list nip; -+ static service_user *hosts_database; -+ service_user *nip; - int no_more; - int rc6 = 0; - int rc4 = 0; - int herrno = 0; - -- no_more = __nss_database_lookup2 ("hosts", NULL, -- "dns [!UNAVAIL=return] files", -- &nip); -+ if (hosts_database == NULL) -+ no_more = __nss_database_lookup2 ("hosts", NULL, -+ "dns [!UNAVAIL=return] files", -+ &hosts_database); -+ else -+ no_more = 0; -+ nip = hosts_database; - - /* Initialize configurations. */ - struct resolv_context *ctx = __resolv_context_get (); -@@ -437,10 +442,10 @@ next_nip: - if (nss_next_action (nip, status[1]) == NSS_ACTION_RETURN) - break; - -- if (nip[1].module == NULL) -+ if (nip->next == NULL) - no_more = -1; - else -- ++nip; -+ nip = nip->next; - } - - /* No result found. Create a negative result record. */ -Index: glibc-2.33/nscd/gai.c -=================================================================== ---- glibc-2.33.orig/nscd/gai.c -+++ glibc-2.33/nscd/gai.c -@@ -48,4 +48,4 @@ - #include - - /* Some variables normally defined in libc. */ --nss_action_list __nss_hosts_database attribute_hidden; -+service_user *__nss_hosts_database attribute_hidden; -Index: glibc-2.33/nscd/initgrcache.c -=================================================================== ---- glibc-2.33.orig/nscd/initgrcache.c -+++ glibc-2.33/nscd/initgrcache.c -@@ -77,8 +77,8 @@ addinitgroupsX (struct database_dyn *db, - dbg_log (_("Reloading \"%s\" in group cache!"), (char *) key); - } - -- static nss_action_list group_database; -- nss_action_list nip; -+ static service_user *group_database; -+ service_user *nip; - int no_more; - - if (group_database == NULL) -@@ -161,10 +161,10 @@ addinitgroupsX (struct database_dyn *db, - && nss_next_action (nip, status) == NSS_ACTION_RETURN) - break; - -- if (nip[1].module == NULL) -+ if (nip->next == NULL) - no_more = -1; - else -- ++nip; -+ nip = nip->next; - } - - bool all_written; -Index: glibc-2.33/nscd/netgroupcache.c -=================================================================== ---- glibc-2.33.orig/nscd/netgroupcache.c -+++ glibc-2.33/nscd/netgroupcache.c -@@ -124,7 +124,7 @@ addgetnetgrentX (struct database_dyn *db - dbg_log (_("Reloading \"%s\" in netgroup cache!"), key); - } - -- static nss_action_list netgroup_database; -+ static service_user *netgroup_database; - time_t timeout; - struct dataset *dataset; - bool cacheable = false; -@@ -175,7 +175,7 @@ addgetnetgrentX (struct database_dyn *db - void *ptr; - } setfct; - -- nss_action_list nip = netgroup_database; -+ service_user *nip = netgroup_database; - int no_more = __nss_lookup (&nip, "setnetgrent", NULL, &setfct.ptr); - while (!no_more) - { -Index: glibc-2.33/nscd/nscd_netgroup.c -=================================================================== ---- glibc-2.33.orig/nscd/nscd_netgroup.c -+++ glibc-2.33/nscd/nscd_netgroup.c -@@ -116,7 +116,7 @@ __nscd_setnetgrent (const char *group, s - datap->data_size = datalen; - datap->cursor = respdata; - datap->first = 1; -- datap->nip = (nss_action_list) -1l; -+ datap->nip = (service_user *) -1l; - datap->known_groups = NULL; - datap->needed_groups = NULL; - -Index: glibc-2.33/nss/Makefile -=================================================================== ---- glibc-2.33.orig/nss/Makefile -+++ glibc-2.33/nss/Makefile -@@ -30,8 +30,7 @@ routines = nsswitch getnssent getnssent - $(addsuffix -lookup,$(databases)) \ - compat-lookup nss_hash nss_files_fopen \ - nss_readline nss_parse_line_result \ -- nss_fgetent_r nss_module nss_action \ -- nss_action_parse nss_database -+ nss_fgetent_r - - # These are the databases that go through nss dispatch. - # Caution: if you add a database here, you must add its real name -@@ -66,8 +65,7 @@ tests-container = \ - tst-nss-test3 \ - tst-nss-files-hosts-long \ - tst-nss-db-endpwent \ -- tst-nss-db-endgrent \ -- tst-reload1 tst-reload2 -+ tst-nss-db-endgrent - - # Tests which need libdl - ifeq (yes,$(build-shared)) -Index: glibc-2.33/nss/XXX-lookup.c -=================================================================== ---- glibc-2.33.orig/nss/XXX-lookup.c -+++ glibc-2.33/nss/XXX-lookup.c -@@ -53,11 +53,12 @@ - #endif - - int --DB_LOOKUP_FCT (nss_action_list *ni, const char *fct_name, const char *fct2_name, -+DB_LOOKUP_FCT (service_user **ni, const char *fct_name, const char *fct2_name, - void **fctp) - { -- if (__nss_database_lookup2 (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING, -- DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0) -+ if (DATABASE_NAME_SYMBOL == NULL -+ && __nss_database_lookup2 (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING, -+ DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0) - return -1; - - *ni = DATABASE_NAME_SYMBOL; -Index: glibc-2.33/nss/compat-lookup.c -=================================================================== ---- glibc-2.33.orig/nss/compat-lookup.c -+++ glibc-2.33/nss/compat-lookup.c -@@ -29,7 +29,7 @@ - glibc 2.7 and earlier and glibc 2.8 and later, even on i386. */ - int - attribute_compat_text_section --__nss_passwd_lookup (nss_action_list *ni, const char *fct_name, void **fctp) -+__nss_passwd_lookup (service_user **ni, const char *fct_name, void **fctp) - { - __set_errno (ENOSYS); - return -1; -@@ -46,11 +46,11 @@ compat_symbol (libc, __nss_hosts_lookup, - - /* These functions were exported under a non-GLIBC_PRIVATE version, - even though it is not usable externally due to the service_user -- (now nss_action_list) type dependency. */ -+ type dependency. */ - - int - attribute_compat_text_section --__nss_next (nss_action_list *ni, const char *fct_name, void **fctp, int status, -+__nss_next (service_user **ni, const char *fct_name, void **fctp, int status, - int all_values) - { - return -1; -@@ -60,7 +60,7 @@ compat_symbol (libc, __nss_next, __nss_n - int - attribute_compat_text_section - __nss_database_lookup (const char *database, const char *alternate_name, -- const char *defconfig, nss_action_list *ni) -+ const char *defconfig, service_user **ni) - { - *ni = NULL; - return -1; -Index: glibc-2.33/nss/function.def -=================================================================== ---- glibc-2.33.orig/nss/function.def -+++ glibc-2.33/nss/function.def -@@ -1,5 +1,5 @@ --/* List of all functions defined for the NSS in GNU C Library. -- Copyright (C) 1996-2021 Free Software Foundation, Inc. -+/* List of functions defined for static NSS in GNU C Library. -+ Copyright (C) 1996-2020 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or -@@ -16,69 +16,63 @@ - License along with the GNU C Library; if not, see - . */ - --/* This list must be kept sorted!!! */ -+/* -+ This is a minimal config. Only services `files' and `dns' are supported. -+*/ - --DEFINE_NSS_FUNCTION (endaliasent) --DEFINE_NSS_FUNCTION (endetherent) --DEFINE_NSS_FUNCTION (endgrent) --DEFINE_NSS_FUNCTION (endhostent) --DEFINE_NSS_FUNCTION (endnetent) --DEFINE_NSS_FUNCTION (endnetgrent) --DEFINE_NSS_FUNCTION (endprotoent) --DEFINE_NSS_FUNCTION (endpwent) --DEFINE_NSS_FUNCTION (endrpcent) --DEFINE_NSS_FUNCTION (endservent) --DEFINE_NSS_FUNCTION (endsgent) --DEFINE_NSS_FUNCTION (endspent) --DEFINE_NSS_FUNCTION (getaliasbyname_r) --DEFINE_NSS_FUNCTION (getaliasent_r) --DEFINE_NSS_FUNCTION (getcanonname_r) --DEFINE_NSS_FUNCTION (getetherent_r) --DEFINE_NSS_FUNCTION (getgrent_r) --DEFINE_NSS_FUNCTION (getgrgid_r) --DEFINE_NSS_FUNCTION (getgrnam_r) --DEFINE_NSS_FUNCTION (gethostbyaddr2_r) --DEFINE_NSS_FUNCTION (gethostbyaddr_r) --DEFINE_NSS_FUNCTION (gethostbyname2_r) --DEFINE_NSS_FUNCTION (gethostbyname3_r) --DEFINE_NSS_FUNCTION (gethostbyname4_r) --DEFINE_NSS_FUNCTION (gethostbyname_r) --DEFINE_NSS_FUNCTION (gethostent_r) --DEFINE_NSS_FUNCTION (gethostton_r) --DEFINE_NSS_FUNCTION (getnetbyaddr_r) --DEFINE_NSS_FUNCTION (getnetbyname_r) --DEFINE_NSS_FUNCTION (getnetent_r) --DEFINE_NSS_FUNCTION (getnetgrent_r) --DEFINE_NSS_FUNCTION (getntohost_r) --DEFINE_NSS_FUNCTION (getprotobyname_r) --DEFINE_NSS_FUNCTION (getprotobynumber_r) --DEFINE_NSS_FUNCTION (getprotoent_r) --DEFINE_NSS_FUNCTION (getpublickey) --DEFINE_NSS_FUNCTION (getpwent_r) --DEFINE_NSS_FUNCTION (getpwnam_r) --DEFINE_NSS_FUNCTION (getpwuid_r) --DEFINE_NSS_FUNCTION (getrpcbyname_r) --DEFINE_NSS_FUNCTION (getrpcbynumber_r) --DEFINE_NSS_FUNCTION (getrpcent_r) --DEFINE_NSS_FUNCTION (getsecretkey) --DEFINE_NSS_FUNCTION (getservbyname_r) --DEFINE_NSS_FUNCTION (getservbyport_r) --DEFINE_NSS_FUNCTION (getservent_r) --DEFINE_NSS_FUNCTION (getsgent_r) --DEFINE_NSS_FUNCTION (getsgnam_r) --DEFINE_NSS_FUNCTION (getspent_r) --DEFINE_NSS_FUNCTION (getspnam_r) --DEFINE_NSS_FUNCTION (initgroups_dyn) --DEFINE_NSS_FUNCTION (netname2user) --DEFINE_NSS_FUNCTION (setaliasent) --DEFINE_NSS_FUNCTION (setetherent) --DEFINE_NSS_FUNCTION (setgrent) --DEFINE_NSS_FUNCTION (sethostent) --DEFINE_NSS_FUNCTION (setnetent) --DEFINE_NSS_FUNCTION (setnetgrent) --DEFINE_NSS_FUNCTION (setprotoent) --DEFINE_NSS_FUNCTION (setpwent) --DEFINE_NSS_FUNCTION (setrpcent) --DEFINE_NSS_FUNCTION (setservent) --DEFINE_NSS_FUNCTION (setsgent) --DEFINE_NSS_FUNCTION (setspent) -+/* aliases */ -+DEFINE_ENT (files, alias) -+DEFINE_GETBY (files, alias, name) -+ -+/* ethers */ -+DEFINE_ENT (files, ether) -+ -+/* group */ -+DEFINE_ENT (files, gr) -+DEFINE_GET (files, grgid) -+DEFINE_GET (files, grnam) -+ -+/* hosts */ -+DEFINE_ENT (files, host) -+DEFINE_GETBY (files, host, addr) -+DEFINE_GETBY (files, host, name) -+DEFINE_GETBY (files, host, name2) -+DEFINE_GET (files, hostton) -+DEFINE_GET (files, ntohost) -+DEFINE_GETBY (dns, host, addr) -+DEFINE_GETBY (dns, host, name) -+DEFINE_GETBY (dns, host, name2) -+ -+/* netgroup */ -+DEFINE_ENT (files, netgr) -+ -+/* networks */ -+DEFINE_ENT (files, net) -+DEFINE_GETBY (files, net, name) -+DEFINE_GETBY (files, net, addr) -+DEFINE_GETBY (dns, net, name) -+DEFINE_GETBY (dns, net, addr) -+ -+/* protocols */ -+DEFINE_ENT (files, proto) -+DEFINE_GETBY (files, proto, name) -+DEFINE_GETBY (files, proto, number) -+ -+/* passwd */ -+DEFINE_ENT (files, pw) -+DEFINE_GET (files, pwnam) -+DEFINE_GET (files, pwuid) -+ -+/* rpc */ -+DEFINE_ENT (files, rpc) -+DEFINE_GETBY (files, rpc, name) -+DEFINE_GETBY (files, rpc, number) -+ -+/* services */ -+DEFINE_ENT (files, serv) -+DEFINE_GETBY (files, serv, name) -+DEFINE_GETBY (files, serv, port) -+ -+/* shadow */ -+DEFINE_ENT (files, sp) -+DEFINE_GET (files, spnam) -Index: glibc-2.33/nss/getXXbyYY_r.c -=================================================================== ---- glibc-2.33.orig/nss/getXXbyYY_r.c -+++ glibc-2.33/nss/getXXbyYY_r.c -@@ -179,7 +179,7 @@ typedef enum nss_status (*lookup_functio - EXTRA_PARAMS); - - /* The lookup function for the first entry of this service. */ --extern int DB_LOOKUP_FCT (nss_action_list *nip, const char *name, -+extern int DB_LOOKUP_FCT (service_user **nip, const char *name, - const char *name2, void **fctp); - libc_hidden_proto (DB_LOOKUP_FCT) - -@@ -189,7 +189,10 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L - size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM - EXTRA_PARAMS) - { -- nss_action_list nip; -+ static bool startp_initialized; -+ static service_user *startp; -+ static lookup_function start_fct; -+ service_user *nip; - int do_merge = 0; - LOOKUP_TYPE mergegrp; - char *mergebuf = NULL; -@@ -224,7 +227,6 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L - PREPROCESS; - #endif - -- - #ifdef HANDLE_DIGITS_DOTS - switch (__nss_hostname_digits_dots (name, resbuf, &buffer, NULL, - buflen, result, &status, AF_VAL, -@@ -262,8 +264,47 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L - } - #endif - -- no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, -- REENTRANT2_NAME_STRING, &fct.ptr); -+ if (! startp_initialized) -+ { -+ no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, -+ REENTRANT2_NAME_STRING, &fct.ptr); -+ if (no_more) -+ { -+ void *tmp_ptr = (service_user *) -1l; -+#ifdef PTR_MANGLE -+ PTR_MANGLE (tmp_ptr); -+#endif -+ startp = tmp_ptr; -+ } -+ else -+ { -+ void *tmp_ptr = fct.l; -+#ifdef PTR_MANGLE -+ PTR_MANGLE (tmp_ptr); -+#endif -+ start_fct = tmp_ptr; -+ tmp_ptr = nip; -+#ifdef PTR_MANGLE -+ PTR_MANGLE (tmp_ptr); -+#endif -+ startp = tmp_ptr; -+ } -+ -+ /* Make sure start_fct and startp are written before -+ startp_initialized. */ -+ atomic_write_barrier (); -+ startp_initialized = true; -+ } -+ else -+ { -+ fct.l = start_fct; -+ nip = startp; -+#ifdef PTR_DEMANGLE -+ PTR_DEMANGLE (fct.l); -+ PTR_DEMANGLE (nip); -+#endif -+ no_more = nip == (service_user *) -1l; -+ } - - while (no_more == 0) - { -Index: glibc-2.33/nss/getXXent_r.c -=================================================================== ---- glibc-2.33.orig/nss/getXXent_r.c -+++ glibc-2.33/nss/getXXent_r.c -@@ -95,11 +95,11 @@ - - /* This handle for the NSS data base is shared between all - set/get/endXXXent functions. */ --static nss_action_list nip; -+static service_user *nip; - /* Remember the last service used since the last call to `endXXent'. */ --static nss_action_list last_nip; --/* Remember the first service_entry across set/get/endent. */ --static nss_action_list startp; -+static service_user *last_nip; -+/* Remember the first service_entry, it's always the same. */ -+static service_user *startp; - - #ifdef STAYOPEN_TMP - /* We need to remember the last `stayopen' flag given by the user -@@ -112,7 +112,7 @@ static STAYOPEN_TMP; - __libc_lock_define_initialized (static, lock) - - /* The lookup function for the first entry of this service. */ --extern int DB_LOOKUP_FCT (nss_action_list *nip, const char *name, -+extern int DB_LOOKUP_FCT (service_user **nip, const char *name, - const char *name2, void **fctp); - libc_hidden_proto (DB_LOOKUP_FCT) - -Index: glibc-2.33/nss/getnssent_r.c -=================================================================== ---- glibc-2.33.orig/nss/getnssent_r.c -+++ glibc-2.33/nss/getnssent_r.c -@@ -25,20 +25,20 @@ - services (left). */ - static int - setup (const char *func_name, db_lookup_function lookup_fct, -- void **fctp, nss_action_list *nip, nss_action_list *startp, int all) -+ void **fctp, service_user **nip, service_user **startp, int all) - { - int no_more; -- if (*startp == NULL || all) -+ if (*startp == NULL) - { - no_more = lookup_fct (nip, func_name, NULL, fctp); -- *startp = no_more ? (nss_action_list) -1l : *nip; -+ *startp = no_more ? (service_user *) -1l : *nip; - } -- else if (*startp == (nss_action_list) -1l) -+ else if (*startp == (service_user *) -1l) - /* No services at all. */ - return 1; - else - { -- if (!*nip) -+ if (all || !*nip) - /* Reset to the beginning of the service list. */ - *nip = *startp; - /* Look up the first function. */ -@@ -49,8 +49,8 @@ setup (const char *func_name, db_lookup_ - - void - __nss_setent (const char *func_name, db_lookup_function lookup_fct, -- nss_action_list *nip, nss_action_list *startp, -- nss_action_list *last_nip, int stayopen, int *stayopen_tmp, -+ service_user **nip, service_user **startp, -+ service_user **last_nip, int stayopen, int *stayopen_tmp, - int res) - { - union -@@ -110,8 +110,8 @@ __nss_setent (const char *func_name, db_ - - void - __nss_endent (const char *func_name, db_lookup_function lookup_fct, -- nss_action_list *nip, nss_action_list *startp, -- nss_action_list *last_nip, int res) -+ service_user **nip, service_user **startp, -+ service_user **last_nip, int res) - { - union - { -@@ -154,8 +154,8 @@ int - __nss_getent_r (const char *getent_func_name, - const char *setent_func_name, - db_lookup_function lookup_fct, -- nss_action_list *nip, nss_action_list *startp, -- nss_action_list *last_nip, int *stayopen_tmp, int res, -+ service_user **nip, service_user **startp, -+ service_user **last_nip, int *stayopen_tmp, int res, - void *resbuf, char *buffer, size_t buflen, - void **result, int *h_errnop) - { -Index: glibc-2.33/nss/nss_action.c -=================================================================== ---- glibc-2.33.orig/nss/nss_action.c -+++ /dev/null -@@ -1,116 +0,0 @@ --/* NSS actions, elements in a nsswitch.conf configuration line. -- Copyright (c) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include -- --#include --#include -- --/* Maintain a global list of NSS action lists. Since most databases -- use the same list of actions, this list is usually short. -- Deduplication in __nss_action_allocate ensures that the list does -- not grow without bounds. */ -- --struct nss_action_list_wrapper --{ -- /* The next element of the list. */ -- struct nss_action_list_wrapper *next; -- -- /* Number of elements in the list (excluding the terminator). */ -- size_t count; -- -- /* NULL-terminated list of actions. */ -- struct nss_action actions[]; --}; -- --/* Toplevel list of allocated NSS action lists. */ --static struct nss_action_list_wrapper *nss_actions; -- --/* Lock covers the nss_actions list. */ --__libc_lock_define (static, nss_actions_lock); -- --/* Returns true if the actions are equal (same module, same actions -- array). */ --static bool --actions_equal (const struct nss_action *a, const struct nss_action *b) --{ -- return a->module == b->module && a->action_bits == b->action_bits; --} -- -- --/* Returns true if COUNT actions at A and B are equal (according to -- actions_equal above). Caller must ensure that either A or B have at -- least COUNT actions. */ --static bool --action_lists_equal (const struct nss_action *a, const struct nss_action *b, -- size_t count) --{ -- for (size_t i = 0; i < count; ++i) -- if (!actions_equal (a + i, b + i)) -- return false; -- return true; --} -- --/* Returns a pre-allocated action list for COUNT actions at ACTIONS, -- or NULL if no such list exists. */ --static nss_action_list --find_allocated (struct nss_action *actions, size_t count) --{ -- for (struct nss_action_list_wrapper *p = nss_actions; p != NULL; p = p->next) -- if (p->count == count && action_lists_equal (p->actions, actions, count)) -- return p->actions; -- return NULL; --} -- --nss_action_list --__nss_action_allocate (struct nss_action *actions, size_t count) --{ -- nss_action_list result = NULL; -- __libc_lock_lock (nss_actions_lock); -- -- result = find_allocated (actions, count); -- if (result == NULL) -- { -- struct nss_action_list_wrapper *wrapper -- = malloc (sizeof (*wrapper) + sizeof (*actions) * count); -- if (wrapper != NULL) -- { -- wrapper->next = nss_actions; -- wrapper->count = count; -- memcpy (wrapper->actions, actions, sizeof (*actions) * count); -- nss_actions = wrapper; -- result = wrapper->actions; -- } -- } -- -- __libc_lock_unlock (nss_actions_lock); -- return result; --} -- --void __libc_freeres_fn_section --__nss_action_freeres (void) --{ -- struct nss_action_list_wrapper *current = nss_actions; -- while (current != NULL) -- { -- struct nss_action_list_wrapper *next = current->next; -- free (current); -- current = next; -- } -- nss_actions = NULL; --} -Index: glibc-2.33/nss/nss_action.h -=================================================================== ---- glibc-2.33.orig/nss/nss_action.h -+++ /dev/null -@@ -1,108 +0,0 @@ --/* NSS actions, elements in a nsswitch.conf configuration line. -- Copyright (c) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#ifndef _NSS_ACTION_H --#define _NSS_ACTION_H -- --#include -- --/* See nss_database.h for a summary of how this relates. */ -- --#include "nsswitch.h" /* For lookup_actions. */ -- --struct nss_module; -- --/* A NSS action pairs a service module with the action for each result -- state. */ --struct nss_action --{ -- /* The service module that provides the functionality (potentially -- not yet loaded). */ -- struct nss_module *module; -- -- /* Action according to result. Two bits for each lookup_actions -- value (from nsswitch.h), indexed by enum nss_status (from nss.h). */ -- unsigned int action_bits; --}; -- --/* Value to add to first nss_status value to get zero. */ --#define NSS_STATUS_BIAS 2 --/* Number of bits per lookup action. */ --#define NSS_BPL 2 --#define NSS_BPL_MASK ((1 << NSS_BPL) - 1) -- --/* Index in actions of an NSS status. Note that in nss/nss.h the -- status starts at -2, and we shift that up to zero by adding 2. -- Thus for example NSS_STATUS_TRYAGAIN, which is -2, would index into -- the 0th bit place as expected. */ --static inline int --nss_actions_bits_index (enum nss_status status) --{ -- return NSS_BPL * (NSS_STATUS_BIAS + status); --} -- --/* Returns the lookup_action value for STATUS in ACTION. */ --static inline lookup_actions --nss_action_get (const struct nss_action *action, enum nss_status status) --{ -- return ((action->action_bits >> nss_actions_bits_index (status)) -- & NSS_BPL_MASK); --} -- --/* Sets the lookup_action value for STATUS in ACTION. */ --static inline void --nss_action_set (struct nss_action *action, -- enum nss_status status, lookup_actions actions) --{ -- int offset = nss_actions_bits_index (status); -- unsigned int mask = NSS_BPL_MASK << offset; -- action->action_bits = ((action->action_bits & ~mask) -- | ((unsigned int) actions << offset)); --} -- --static inline void --nss_action_set_all (struct nss_action *action, lookup_actions actions) --{ -- unsigned int bits = actions & NSS_BPL_MASK; -- action->action_bits = ( bits -- | (bits << (NSS_BPL * 1)) -- | (bits << (NSS_BPL * 2)) -- | (bits << (NSS_BPL * 3)) -- | (bits << (NSS_BPL * 4)) -- ); --} -- --/* A list of struct nss_action objects in array terminated by an -- action with a NULL module. */ --typedef struct nss_action *nss_action_list; -- --/* Returns a pointer to an allocated NSS action list that has COUNT -- actions that matches the array at ACTIONS. */ --nss_action_list __nss_action_allocate (struct nss_action *actions, -- size_t count) attribute_hidden; -- --/* Returns a pointer to a list allocated by __nss_action_allocate, or -- NULL on error. ENOMEM means a (temporary) memory allocation error, -- EINVAL means that LINE is syntactically invalid. */ --nss_action_list __nss_action_parse (const char *line); -- --/* Called from __libc_freeres. */ --void __nss_action_freeres (void) attribute_hidden; -- -- --#endif /* _NSS_ACTION_H */ -Index: glibc-2.33/nss/nss_action_parse.c -=================================================================== ---- glibc-2.33.orig/nss/nss_action_parse.c -+++ /dev/null -@@ -1,191 +0,0 @@ --/* Parse a service line from nsswitch.conf. -- Copyright (c) 1996-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include -- --#include --#include --#include -- --/* Staging area during parsing. */ --#define DYNARRAY_STRUCT action_list --#define DYNARRAY_ELEMENT struct nss_action --#define DYNARRAY_PREFIX action_list_ --#include -- --/* Skip whitespace in line[]. */ --#define SKIP_WS() \ -- while (line[0] != '\0' && isspace (line[0])) \ -- ++line; -- --/* Read the source names: -- `( ( "[" "!"? ( "=" )+ "]" )? )*' -- */ --static bool --nss_action_parse (const char *line, struct action_list *result) --{ -- while (1) -- { -- SKIP_WS (); -- if (line[0] == '\0') -- /* No more sources specified. */ -- return true; -- -- /* Read identifier. */ -- const char *name = line; -- while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') -- ++line; -- if (name == line) -- return true; -- -- struct nss_action new_service -- = { .module = __nss_module_allocate (name, line - name), }; -- if (new_service.module == NULL) -- { -- /* Memory allocation error. */ -- action_list_mark_failed (result); -- return false; -- } -- nss_action_set_all (&new_service, NSS_ACTION_CONTINUE); -- nss_action_set (&new_service, NSS_STATUS_SUCCESS, NSS_ACTION_RETURN); -- nss_action_set (&new_service, NSS_STATUS_RETURN, NSS_ACTION_RETURN); -- -- SKIP_WS (); -- -- if (line[0] == '[') -- { -- /* Read criterions. */ -- -- /* Skip the '['. */ -- ++line; -- SKIP_WS (); -- -- do -- { -- int not; -- enum nss_status status; -- lookup_actions action; -- -- /* Grok ! before name to mean all statuses but that one. */ -- not = line[0] == '!'; -- if (not) -- ++line; -- -- /* Read status name. */ -- name = line; -- while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' -- && line[0] != ']') -- ++line; -- -- /* Compare with known statuses. */ -- if (line - name == 7) -- { -- if (__strncasecmp (name, "SUCCESS", 7) == 0) -- status = NSS_STATUS_SUCCESS; -- else if (__strncasecmp (name, "UNAVAIL", 7) == 0) -- status = NSS_STATUS_UNAVAIL; -- else -- return false; -- } -- else if (line - name == 8) -- { -- if (__strncasecmp (name, "NOTFOUND", 8) == 0) -- status = NSS_STATUS_NOTFOUND; -- else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) -- status = NSS_STATUS_TRYAGAIN; -- else -- return false; -- } -- else -- return false; -- -- SKIP_WS (); -- if (line[0] != '=') -- return false; -- -- /* Skip the '='. */ -- ++line; -- SKIP_WS (); -- name = line; -- while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' -- && line[0] != ']') -- ++line; -- -- if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) -- action = NSS_ACTION_RETURN; -- else if (line - name == 8 -- && __strncasecmp (name, "CONTINUE", 8) == 0) -- action = NSS_ACTION_CONTINUE; -- else if (line - name == 5 -- && __strncasecmp (name, "MERGE", 5) == 0) -- action = NSS_ACTION_MERGE; -- else -- return false; -- -- if (not) -- { -- /* Save the current action setting for this status, -- set them all to the given action, and reset this one. */ -- const lookup_actions save -- = nss_action_get (&new_service, status); -- nss_action_set_all (&new_service, action); -- nss_action_set (&new_service, status, save); -- } -- else -- nss_action_set (&new_service, status, action); -- -- SKIP_WS (); -- } -- while (line[0] != ']'); -- -- /* Skip the ']'. */ -- ++line; -- } -- -- action_list_add (result, new_service); -- } --} -- --nss_action_list -- __nss_action_parse (const char *line) --{ -- struct action_list list; -- action_list_init (&list); -- if (nss_action_parse (line, &list)) -- { -- size_t size; -- struct nss_action null_service -- = { .module = NULL, }; -- -- action_list_add (&list, null_service); -- size = action_list_size (&list); -- return __nss_action_allocate (action_list_begin (&list), size); -- } -- else if (action_list_has_failed (&list)) -- { -- /* Memory allocation error. */ -- __set_errno (ENOMEM); -- return NULL; -- } -- else -- { -- /* Parse error. */ -- __set_errno (EINVAL); -- return NULL; -- } --} -Index: glibc-2.33/nss/nss_compat/compat-grp.c -=================================================================== ---- glibc-2.33.orig/nss/nss_compat/compat-grp.c -+++ glibc-2.33/nss/nss_compat/compat-grp.c -@@ -30,7 +30,7 @@ - - NSS_DECLARE_MODULE_FUNCTIONS (compat) - --static nss_action_list ni; -+static service_user *ni; - static enum nss_status (*setgrent_impl) (int stayopen); - static enum nss_status (*getgrnam_r_impl) (const char *name, - struct group * grp, char *buffer, -Index: glibc-2.33/nss/nss_compat/compat-initgroups.c -=================================================================== ---- glibc-2.33.orig/nss/nss_compat/compat-initgroups.c -+++ glibc-2.33/nss/nss_compat/compat-initgroups.c -@@ -33,7 +33,7 @@ - - NSS_DECLARE_MODULE_FUNCTIONS (compat) - --static nss_action_list ni; -+static service_user *ni; - static enum nss_status (*initgroups_dyn_impl) (const char *, gid_t, - long int *, long int *, - gid_t **, long int, int *); -Index: glibc-2.33/nss/nss_compat/compat-pwd.c -=================================================================== ---- glibc-2.33.orig/nss/nss_compat/compat-pwd.c -+++ glibc-2.33/nss/nss_compat/compat-pwd.c -@@ -34,7 +34,7 @@ - - NSS_DECLARE_MODULE_FUNCTIONS (compat) - --static nss_action_list ni; -+static service_user *ni; - static enum nss_status (*setpwent_impl) (int stayopen); - static enum nss_status (*getpwnam_r_impl) (const char *name, - struct passwd * pwd, char *buffer, -Index: glibc-2.33/nss/nss_compat/compat-spwd.c -=================================================================== ---- glibc-2.33.orig/nss/nss_compat/compat-spwd.c -+++ glibc-2.33/nss/nss_compat/compat-spwd.c -@@ -34,7 +34,7 @@ - - NSS_DECLARE_MODULE_FUNCTIONS (compat) - --static nss_action_list ni; -+static service_user *ni; - static enum nss_status (*setspent_impl) (int stayopen); - static enum nss_status (*getspnam_r_impl) (const char *name, struct spwd * sp, - char *buffer, size_t buflen, -Index: glibc-2.33/nss/nss_database.c -=================================================================== ---- glibc-2.33.orig/nss/nss_database.c -+++ /dev/null -@@ -1,497 +0,0 @@ --/* Mapping NSS services to action lists. -- Copyright (C) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include "nss_database.h" -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --struct nss_database_state --{ -- struct nss_database_data data; -- __libc_lock_define (, lock); -- /* If "/" changes, we switched into a container and do NOT want to -- reload anything. This data must be persistent across -- reloads. */ -- ino64_t root_ino; -- dev_t root_dev; --}; -- -- --/* Global NSS database state. Underlying type is "struct -- nss_database_state *" but the allocate_once API requires -- "void *". */ --static void *global_database_state; -- --/* Allocate and return pointer to nss_database_state object or -- on failure return NULL. */ --static void * --global_state_allocate (void *closure) --{ -- struct nss_database_state *result = malloc (sizeof (*result)); -- if (result != NULL) -- { -- result->data.nsswitch_conf.size = -1; /* Force reload. */ -- memset (result->data.services, 0, sizeof (result->data.services)); -- result->data.initialized = true; -- result->data.reload_disabled = false; -- __libc_lock_init (result->lock); -- result->root_ino = 0; -- result->root_dev = 0; -- } -- return result; --} -- --/* Return pointer to global NSS database state, allocating as -- required, or returning NULL on failure. */ --static struct nss_database_state * --nss_database_state_get (void) --{ -- return allocate_once (&global_database_state, global_state_allocate, -- NULL, NULL); --} -- --/* Database default selections. nis/compat mappings get turned into -- "files" for !LINK_OBSOLETE_NSL configurations. */ --enum nss_database_default --{ -- nss_database_default_defconfig = 0, /* "nis [NOTFOUND=return] files". */ -- nss_database_default_compat, /* "compat [NOTFOUND=return] files". */ -- nss_database_default_dns, /* "dns [!UNAVAIL=return] files". */ -- nss_database_default_files, /* "files". */ -- nss_database_default_nis, /* "nis". */ -- nss_database_default_nis_nisplus, /* "nis nisplus". */ -- nss_database_default_none, /* Empty list. */ -- -- NSS_DATABASE_DEFAULT_COUNT /* Number of defaults. */ --}; -- --/* Databases not listed default to nss_database_default_defconfig. */ --static const char per_database_defaults[NSS_DATABASE_COUNT] = -- { -- [nss_database_group] = nss_database_default_compat, -- [nss_database_gshadow] = nss_database_default_files, -- [nss_database_hosts] = nss_database_default_dns, -- [nss_database_initgroups] = nss_database_default_none, -- [nss_database_networks] = nss_database_default_dns, -- [nss_database_passwd] = nss_database_default_compat, -- [nss_database_publickey] = nss_database_default_nis_nisplus, -- [nss_database_shadow] = nss_database_default_compat, -- }; -- --struct nss_database_default_cache --{ -- nss_action_list caches[NSS_DATABASE_DEFAULT_COUNT]; --}; -- --static bool --nss_database_select_default (struct nss_database_default_cache *cache, -- enum nss_database db, nss_action_list *result) --{ -- enum nss_database_default def = per_database_defaults[db]; -- *result = cache->caches[def]; -- if (*result != NULL) -- return true; -- -- /* Determine the default line string. */ -- const char *line; -- switch (def) -- { --#ifdef LINK_OBSOLETE_NSL -- case nss_database_default_defconfig: -- line = "nis [NOTFOUND=return] files"; -- break; -- case nss_database_default_compat: -- line = "compat [NOTFOUND=return] files"; -- break; --#endif -- -- case nss_database_default_dns: -- line = "dns [!UNAVAIL=return] files"; -- break; -- -- case nss_database_default_files: --#ifndef LINK_OBSOLETE_NSL -- case nss_database_default_defconfig: -- case nss_database_default_compat: --#endif -- line = "files"; -- break; -- -- case nss_database_default_nis: -- line = "nis"; -- break; -- -- case nss_database_default_nis_nisplus: -- line = "nis nisplus"; -- break; -- -- case nss_database_default_none: -- /* Very special case: Leave *result as NULL. */ -- return true; -- -- case NSS_DATABASE_DEFAULT_COUNT: -- __builtin_unreachable (); -- } -- if (def < 0 || def >= NSS_DATABASE_DEFAULT_COUNT) -- /* Tell GCC that line is initialized. */ -- __builtin_unreachable (); -- -- *result = __nss_action_parse (line); -- if (*result == NULL) -- { -- assert (errno == ENOMEM); -- return false; -- } -- else -- return true; --} -- --/* database_name must be large enough for each individual name plus a -- null terminator. */ --typedef char database_name[11]; --#define DEFINE_DATABASE(name) \ -- _Static_assert (sizeof (#name) <= sizeof (database_name), #name); --#include "databases.def" --#undef DEFINE_DATABASE -- --static const database_name nss_database_name_array[] = -- { --#define DEFINE_DATABASE(name) #name, --#include "databases.def" --#undef DEFINE_DATABASE -- }; -- --static int --name_search (const void *left, const void *right) --{ -- return strcmp (left, right); --} -- --static int --name_to_database_index (const char *name) --{ -- database_name *name_entry = bsearch (name, nss_database_name_array, -- array_length (nss_database_name_array), -- sizeof (database_name), name_search); -- if (name_entry == NULL) -- return -1; -- return name_entry - nss_database_name_array; --} -- --static bool --process_line (struct nss_database_data *data, char *line) --{ -- /* Ignore leading white spaces. ATTENTION: this is different from -- what is implemented in Solaris. The Solaris man page says a line -- beginning with a white space character is ignored. We regard -- this as just another misfeature in Solaris. */ -- while (isspace (line[0])) -- ++line; -- -- /* Recognize ` ":"'. */ -- char *name = line; -- while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') -- ++line; -- if (line[0] == '\0' || name == line) -- /* Syntax error. Skip this line. */ -- return true; -- while (line[0] != '\0' && (isspace (line[0]) || line[0] == ':')) -- *line++ = '\0'; -- -- int db = name_to_database_index (name); -- if (db < 0) -- /* Not our database e.g. sudoers, automount, etc. */ -- return true; -- -- nss_action_list result = __nss_action_parse (line); -- if (result == NULL) -- return false; -- data->services[db] = result; -- return true; --} -- --int --__nss_configure_lookup (const char *dbname, const char *service_line) --{ -- int db; -- nss_action_list result; -- struct nss_database_state *local; -- -- /* Convert named database to index. */ -- db = name_to_database_index (dbname); -- if (db < 0) -- /* Not our database (e.g., sudoers). */ -- return -1; -- -- /* Force any load/cache/read whatever to happen, so we can override -- it. */ -- __nss_database_get (db, &result); -- -- local = nss_database_state_get (); -- -- result = __nss_action_parse (service_line); -- if (result == NULL) -- return -1; -- -- atomic_store_release (&local->data.reload_disabled, 1); -- local->data.services[db] = result; -- --#ifdef USE_NSCD -- __nss_database_custom[db] = true; --#endif -- -- return 0; --} -- --/* Iterate over the lines in FP, parse them, and store them in DATA. -- Return false on memory allocation failure, true on success. */ --static bool --nss_database_reload_1 (struct nss_database_data *data, FILE *fp) --{ -- char *line = NULL; -- size_t line_allocated = 0; -- bool result = false; -- -- while (true) -- { -- ssize_t ret = __getline (&line, &line_allocated, fp); -- if (__ferror_unlocked (fp)) -- break; -- if (__feof_unlocked (fp)) -- { -- result = true; -- break; -- } -- assert (ret > 0); -- (void) ret; /* For NDEBUG builds. */ -- -- if (!process_line (data, line)) -- break; -- } -- -- free (line); -- return result; --} -- --static bool --nss_database_reload (struct nss_database_data *staging, -- struct file_change_detection *initial) --{ -- FILE *fp = fopen (_PATH_NSSWITCH_CONF, "rce"); -- if (fp == NULL) -- switch (errno) -- { -- case EACCES: -- case EISDIR: -- case ELOOP: -- case ENOENT: -- case ENOTDIR: -- case EPERM: -- /* Ignore these errors. They are persistent errors caused -- by file system contents. */ -- break; -- default: -- /* Other errors refer to resource allocation problems and -- need to be handled by the application. */ -- return false; -- } -- else -- /* No other threads have access to fp. */ -- __fsetlocking (fp, FSETLOCKING_BYCALLER); -- -- bool ok = true; -- if (fp != NULL) -- ok = nss_database_reload_1 (staging, fp); -- -- /* Apply defaults. */ -- if (ok) -- { -- struct nss_database_default_cache cache = { }; -- for (int i = 0; i < NSS_DATABASE_COUNT; ++i) -- if (staging->services[i] == NULL) -- { -- ok = nss_database_select_default (&cache, i, -- &staging->services[i]); -- if (!ok) -- break; -- } -- } -- -- if (ok) -- ok = __file_change_detection_for_fp (&staging->nsswitch_conf, fp); -- -- if (fp != NULL) -- { -- int saved_errno = errno; -- fclose (fp); -- __set_errno (saved_errno); -- } -- -- if (ok && !__file_is_unchanged (&staging->nsswitch_conf, initial)) -- /* Reload is required because the file changed while reading. */ -- staging->nsswitch_conf.size = -1; -- -- return ok; --} -- --static bool --nss_database_check_reload_and_get (struct nss_database_state *local, -- nss_action_list *result, -- enum nss_database database_index) --{ -- struct stat64 str; -- -- /* Acquire MO is needed because the thread that sets reload_disabled -- may have loaded the configuration first, so synchronize with the -- Release MO store there. */ -- if (atomic_load_acquire (&local->data.reload_disabled)) -- { -- *result = local->data.services[database_index]; -- /* No reload, so there is no error. */ -- return true; -- } -- -- struct file_change_detection initial; -- if (!__file_change_detection_for_path (&initial, _PATH_NSSWITCH_CONF)) -- return false; -- -- __libc_lock_lock (local->lock); -- if (__file_is_unchanged (&initial, &local->data.nsswitch_conf)) -- { -- /* Configuration is up-to-date. Read it and return it to the -- caller. */ -- *result = local->data.services[database_index]; -- __libc_lock_unlock (local->lock); -- return true; -- } -- -- /* Before we reload, verify that "/" hasn't changed. We assume that -- errors here are very unlikely, but the chance that we're entering -- a container is also very unlikely, so we err on the side of both -- very unlikely things not happening at the same time. */ -- if (__stat64 ("/", &str) != 0 -- || (local->root_ino != 0 -- && (str.st_ino != local->root_ino -- || str.st_dev != local->root_dev))) -- { -- /* Change detected; disable reloading. */ -- atomic_store_release (&local->data.reload_disabled, 1); -- __libc_lock_unlock (local->lock); -- __nss_module_disable_loading (); -- return true; -- } -- local->root_ino = str.st_ino; -- local->root_dev = str.st_dev; -- __libc_lock_unlock (local->lock); -- -- /* Avoid overwriting the global configuration until we have loaded -- everything successfully. Otherwise, if the file change -- information changes back to what is in the global configuration, -- the lookups would use the partially-written configuration. */ -- struct nss_database_data staging = { .initialized = true, }; -- -- bool ok = nss_database_reload (&staging, &initial); -- -- if (ok) -- { -- __libc_lock_lock (local->lock); -- -- /* See above for memory order. */ -- if (!atomic_load_acquire (&local->data.reload_disabled)) -- /* This may go back in time if another thread beats this -- thread with the update, but in this case, a reload happens -- on the next NSS call. */ -- local->data = staging; -- -- *result = local->data.services[database_index]; -- __libc_lock_unlock (local->lock); -- } -- -- return ok; --} -- --bool --__nss_database_get (enum nss_database db, nss_action_list *actions) --{ -- struct nss_database_state *local = nss_database_state_get (); -- return nss_database_check_reload_and_get (local, actions, db); --} -- --nss_action_list --__nss_database_get_noreload (enum nss_database db) --{ -- /* There must have been a previous __nss_database_get call. */ -- struct nss_database_state *local = atomic_load_acquire (&global_database_state); -- assert (local != NULL); -- -- __libc_lock_lock (local->lock); -- nss_action_list result = local->data.services[db]; -- __libc_lock_unlock (local->lock); -- return result; --} -- --void __libc_freeres_fn_section --__nss_database_freeres (void) --{ -- free (global_database_state); -- global_database_state = NULL; --} -- --void --__nss_database_fork_prepare_parent (struct nss_database_data *data) --{ -- /* Do not use allocate_once to trigger loading unnecessarily. */ -- struct nss_database_state *local = atomic_load_acquire (&global_database_state); -- if (local == NULL) -- data->initialized = false; -- else -- { -- /* Make a copy of the configuration. This approach was chosen -- because it avoids acquiring the lock during the actual -- fork. */ -- __libc_lock_lock (local->lock); -- *data = local->data; -- __libc_lock_unlock (local->lock); -- } --} -- --void --__nss_database_fork_subprocess (struct nss_database_data *data) --{ -- struct nss_database_state *local = atomic_load_acquire (&global_database_state); -- if (data->initialized) -- { -- /* Restore the state at the point of the fork. */ -- assert (local != NULL); -- local->data = *data; -- __libc_lock_init (local->lock); -- } -- else if (local != NULL) -- /* The NSS configuration was loaded concurrently during fork. We -- do not know its state, so we need to discard it. */ -- global_database_state = NULL; --} -Index: glibc-2.33/nss/nss_database.h -=================================================================== ---- glibc-2.33.orig/nss/nss_database.h -+++ /dev/null -@@ -1,88 +0,0 @@ --/* Mapping NSS services to action lists. -- Copyright (C) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#ifndef _NSS_DATABASE_H --#define _NSS_DATABASE_H -- --#include -- --/* Each "line" in nsswitch.conf maps a supported database (example: -- passwd) to one or more name service providers (example: files dns). -- Internally, each name service provider (example: dns) is a -- dynamically loadable module (i.e. libnss_dns.so), managed by -- nss_module.h. The sequence of providers and rules (example: files -- [SUCCESS=RETURN] dns) is mapped by nss_action.h to a cached entry -- which encodes the sequence of modules and rules. Keeping track of -- all supported databases and their corresponding actions is done -- here. -- -- The key entry is __nss_database_get, which provides a set of -- actions which can be used with nss_lookup_function() and -- nss_next(). Callers should assume that these functions are fast, -- and should not cache the result longer than needed. */ -- --#include "nss_action.h" -- --/* The enumeration literal in enum nss_database for the database NAME -- (e.g., nss_database_hosts for hosts). */ --#define NSS_DATABASE_LITERAL(name) nss_database_##name -- --enum nss_database --{ --#define DEFINE_DATABASE(name) NSS_DATABASE_LITERAL (name), --#include "databases.def" --#undef DEFINE_DATABASE -- -- /* Total number of databases. */ -- NSS_DATABASE_COUNT --}; -- -- --/* Looks up the action list for DB and stores it in *ACTIONS. Returns -- true on success or false on failure. Success can mean that -- *ACTIONS is NULL. */ --bool __nss_database_get (enum nss_database db, nss_action_list *actions) -- attribute_hidden; -- --/* Like __nss_database_get, but does not reload /etc/nsswitch.conf -- from disk. This assumes that there has been a previous successful -- __nss_database_get call (which may not have returned any data). */ --nss_action_list __nss_database_get_noreload (enum nss_database db) -- attribute_hidden; -- --/* Called from __libc_freeres. */ --void __nss_database_freeres (void) attribute_hidden; -- --/* Internal type. Exposed only for fork handling purposes. */ --struct nss_database_data --{ -- struct file_change_detection nsswitch_conf; -- nss_action_list services[NSS_DATABASE_COUNT]; -- int reload_disabled; /* Actually bool; int for atomic access. */ -- bool initialized; --}; -- --/* Called by fork in the parent process, before forking. */ --void __nss_database_fork_prepare_parent (struct nss_database_data *data) -- attribute_hidden; -- --/* Called by fork in the new subprocess, after forking. */ --void __nss_database_fork_subprocess (struct nss_database_data *data) -- attribute_hidden; -- --#endif /* _NSS_DATABASE_H */ -Index: glibc-2.33/nss/nss_module.c -=================================================================== ---- glibc-2.33.orig/nss/nss_module.c -+++ /dev/null -@@ -1,379 +0,0 @@ --/* Global list of NSS service modules. -- Copyright (c) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include --#include --#include -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef LINK_OBSOLETE_NSL --# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" --# define DEFAULT_DEFCONFIG "nis [NOTFOUND=return] files" --#else --# define DEFAULT_CONFIG "files" --# define DEFAULT_DEFCONFIG "files" --#endif -- --/* Suffix after .so of NSS service modules. This is a bit of magic, -- but we assume LIBNSS_FILES_SO looks like "libnss_files.so.2" and we -- want a pointer to the ".2" part. We have no API to extract this -- except through the auto-generated lib-names.h and some static -- pointer manipulation. The "-1" accounts for the trailing NUL -- included in the sizeof. */ --static const char *const __nss_shlib_revision -- = LIBNSS_FILES_SO + sizeof("libnss_files.so") - 1; -- --/* A single-linked list used to implement a mapping from service names -- to NSS modules. (Most systems only use five or so modules, so a -- list is sufficient here.) Elements of this list are never freed -- during normal operation. */ --static struct nss_module *nss_module_list; -- --/* Covers the list and also loading of individual NSS service -- modules. */ --__libc_lock_define (static, nss_module_list_lock); -- --#if defined USE_NSCD && (!defined DO_STATIC_NSS || defined SHARED) --/* Nonzero if this is the nscd process. */ --static bool is_nscd; --/* The callback passed to the init functions when nscd is used. */ --static void (*nscd_init_cb) (size_t, struct traced_file *); --#endif -- --/* Allocate the service NAME with length NAME_LENGTH. If the service -- is already allocated in the nss_module_list cache then we return a -- pointer to the struct nss_module, otherwise we try to allocate a -- new struct nss_module entry and add it to the global -- nss_modules_list cache. If we fail to allocate the entry we return -- NULL. Failure to allocate the entry is always transient. */ --struct nss_module * --__nss_module_allocate (const char *name, size_t name_length) --{ -- __libc_lock_lock (nss_module_list_lock); -- -- struct nss_module *result = NULL; -- for (struct nss_module *p = nss_module_list; p != NULL; p = p->next) -- if (strncmp (p->name, name, name_length) == 0 -- && p->name[name_length] == '\0') -- { -- /* Return the previously existing object. */ -- result = p; -- break; -- } -- -- if (result == NULL) -- { -- /* Allocate a new list entry if the name was not found in the -- list. */ -- result = malloc (sizeof (*result) + name_length + 1); -- if (result != NULL) -- { -- result->state = nss_module_uninitialized; -- memcpy (result->name, name, name_length); -- result->name[name_length] = '\0'; -- result->handle = NULL; -- result->next = nss_module_list; -- nss_module_list = result; -- } -- } -- -- __libc_lock_unlock (nss_module_list_lock); -- return result; --} -- --/* Long enough to store the name of any function in the -- nss_function_name_array list below, as getprotobynumber_r is the -- longest entry in that list. */ --typedef char function_name[sizeof("getprotobynumber_r")]; -- --static const function_name nss_function_name_array[] = -- { --#undef DEFINE_NSS_FUNCTION --#define DEFINE_NSS_FUNCTION(x) #x, --#include "function.def" -- }; -- --/* Internal implementation of __nss_module_load. */ --static bool --module_load (struct nss_module *module) --{ -- void *handle; -- { -- char *shlib_name; -- if (__asprintf (&shlib_name, "libnss_%s.so%s", -- module->name, __nss_shlib_revision) < 0) -- /* This is definitely a temporary failure. Do not update -- module->state. This will trigger another attempt at the next -- call. */ -- return false; -- -- handle = __libc_dlopen (shlib_name); -- free (shlib_name); -- } -- -- /* Failing to load the module can be caused by several different -- scenarios. One such scenario is that the module has been removed -- from the disk. In which case the in-memory version is all that -- we have, and if the module->state indidates it is loaded then we -- can use it. */ -- if (handle == NULL) -- { -- /* dlopen failure. We do not know if this a temporary or -- permanent error. See bug 22041. Update the state using the -- double-checked locking idiom. */ -- -- __libc_lock_lock (nss_module_list_lock); -- bool result = result; -- switch ((enum nss_module_state) atomic_load_acquire (&module->state)) -- { -- case nss_module_uninitialized: -- atomic_store_release (&module->state, nss_module_failed); -- result = false; -- break; -- case nss_module_loaded: -- result = true; -- break; -- case nss_module_failed: -- result = false; -- break; -- } -- __libc_lock_unlock (nss_module_list_lock); -- return result; -- } -- -- nss_module_functions_untyped pointers; -- -- /* Look up and store locally all the function pointers we may need -- later. Doing this now means the data will not change in the -- future. */ -- for (size_t idx = 0; idx < array_length (nss_function_name_array); ++idx) -- { -- char *function_name; -- if (__asprintf (&function_name, "_nss_%s_%s", -- module->name, nss_function_name_array[idx]) < 0) -- { -- /* Definitely a temporary error. */ -- __libc_dlclose (handle); -- return false; -- } -- pointers[idx] = __libc_dlsym (handle, function_name); -- free (function_name); --#ifdef PTR_MANGLE -- PTR_MANGLE (pointers[idx]); --#endif -- } -- --# ifdef USE_NSCD -- if (is_nscd) -- { -- /* Call the init function when nscd is used. */ -- size_t initlen = (5 + strlen (module->name) -- + strlen ("_init") + 1); -- char init_name[initlen]; -- -- /* Construct the init function name. */ -- __stpcpy (__stpcpy (__stpcpy (init_name, -- "_nss_"), -- module->name), -- "_init"); -- -- /* Find the optional init function. */ -- void (*ifct) (void (*) (size_t, struct traced_file *)) -- = __libc_dlsym (handle, init_name); -- if (ifct != NULL) -- { -- void (*cb) (size_t, struct traced_file *) = nscd_init_cb; --# ifdef PTR_DEMANGLE -- PTR_DEMANGLE (cb); --# endif -- ifct (cb); -- } -- } --# endif -- -- /* Install the function pointers, following the double-checked -- locking idiom. Delay this after all processing, in case loading -- the module triggers unwinding. */ -- __libc_lock_lock (nss_module_list_lock); -- switch ((enum nss_module_state) atomic_load_acquire (&module->state)) -- { -- case nss_module_uninitialized: -- case nss_module_failed: -- memcpy (module->functions.untyped, pointers, -- sizeof (module->functions.untyped)); -- module->handle = handle; -- /* Synchronizes with unlocked __nss_module_load atomic_load_acquire. */ -- atomic_store_release (&module->state, nss_module_loaded); -- break; -- case nss_module_loaded: -- /* If the module was already loaded, close our own handle. This -- does not actually unload the modules, only the reference -- counter is decremented for the loaded module. */ -- __libc_dlclose (handle); -- break; -- } -- __libc_lock_unlock (nss_module_list_lock); -- return true; --} -- --/* Force the module identified by MODULE to be loaded. We return -- false if the module could not be loaded, true otherwise. Loading -- the module requires looking up all the possible interface APIs and -- caching the results. */ --bool --__nss_module_load (struct nss_module *module) --{ -- switch ((enum nss_module_state) atomic_load_acquire (&module->state)) -- { -- case nss_module_uninitialized: -- return module_load (module); -- case nss_module_loaded: -- /* Loading has already succeeded. */ -- return true; -- case nss_module_failed: -- /* Loading previously failed. */ -- return false; -- } -- __builtin_unreachable (); --} -- --static int --name_search (const void *left, const void *right) --{ -- return strcmp (left, right); --} -- --/* Load module MODULE (if it isn't already) and return a pointer to -- the module's implementation of NAME, otherwise return NULL on -- failure or error. */ --void * --__nss_module_get_function (struct nss_module *module, const char *name) --{ -- if (!__nss_module_load (module)) -- return NULL; -- -- function_name *name_entry = bsearch (name, nss_function_name_array, -- array_length (nss_function_name_array), -- sizeof (function_name), name_search); -- assert (name_entry != NULL); -- size_t idx = name_entry - nss_function_name_array; -- void *fptr = module->functions.untyped[idx]; --#ifdef PTR_DEMANGLE -- PTR_DEMANGLE (fptr); --#endif -- return fptr; --} -- --#if defined SHARED && defined USE_NSCD --/* Load all libraries for the service. */ --static void --nss_load_all_libraries (const char *service, const char *def) --{ -- nss_action_list ni = NULL; -- -- if (__nss_database_lookup2 (service, NULL, def, &ni) == 0) -- while (ni->module != NULL) -- { -- __nss_module_load (ni->module); -- ++ni; -- } --} -- --define_traced_file (pwd, _PATH_NSSWITCH_CONF); --define_traced_file (grp, _PATH_NSSWITCH_CONF); --define_traced_file (hst, _PATH_NSSWITCH_CONF); --define_traced_file (serv, _PATH_NSSWITCH_CONF); --define_traced_file (netgr, _PATH_NSSWITCH_CONF); -- --/* Called by nscd and nscd alone. */ --void --__nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) --{ -- void (*cb1) (size_t, struct traced_file *); -- cb1 = cb; --# ifdef PTR_MANGLE -- PTR_MANGLE (cb); --# endif -- nscd_init_cb = cb; -- is_nscd = true; -- -- /* Find all the relevant modules so that the init functions are called. */ -- nss_load_all_libraries ("passwd", DEFAULT_CONFIG); -- nss_load_all_libraries ("group", DEFAULT_CONFIG); -- nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files"); -- nss_load_all_libraries ("services", NULL); -- -- /* Make sure NSCD purges its cache if nsswitch.conf changes. */ -- init_traced_file (&pwd_traced_file.file, _PATH_NSSWITCH_CONF, 0); -- cb1 (pwddb, &pwd_traced_file.file); -- init_traced_file (&grp_traced_file.file, _PATH_NSSWITCH_CONF, 0); -- cb1 (grpdb, &grp_traced_file.file); -- init_traced_file (&hst_traced_file.file, _PATH_NSSWITCH_CONF, 0); -- cb1 (hstdb, &hst_traced_file.file); -- init_traced_file (&serv_traced_file.file, _PATH_NSSWITCH_CONF, 0); -- cb1 (servdb, &serv_traced_file.file); -- init_traced_file (&netgr_traced_file.file, _PATH_NSSWITCH_CONF, 0); -- cb1 (netgrdb, &netgr_traced_file.file); -- -- /* Disable all uses of NSCD. */ -- __nss_not_use_nscd_passwd = -1; -- __nss_not_use_nscd_group = -1; -- __nss_not_use_nscd_hosts = -1; -- __nss_not_use_nscd_services = -1; -- __nss_not_use_nscd_netgroup = -1; --} --#endif -- --/* Block attempts to dlopen any module we haven't already opened. */ --void --__nss_module_disable_loading (void) --{ -- __libc_lock_lock (nss_module_list_lock); -- -- for (struct nss_module *p = nss_module_list; p != NULL; p = p->next) -- if (p->state == nss_module_uninitialized) -- p->state = nss_module_failed; -- -- __libc_lock_unlock (nss_module_list_lock); --} -- --void __libc_freeres_fn_section --__nss_module_freeres (void) --{ -- struct nss_module *current = nss_module_list; -- while (current != NULL) -- { -- if (current->state == nss_module_loaded) -- __libc_dlclose (current->handle); -- -- struct nss_module *next = current->next; -- free (current); -- current = next; -- } -- nss_module_list = NULL; --} -Index: glibc-2.33/nss/nss_module.h -=================================================================== ---- glibc-2.33.orig/nss/nss_module.h -+++ /dev/null -@@ -1,96 +0,0 @@ --/* Global list of NSS service modules. -- Copyright (c) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#ifndef _NSS_MODULE_H --#define _NSS_MODULE_H -- --#include --#include -- --/* See nss_database.h for a summary of how this relates. */ -- --/* Typed function pointers for all functions that can be defined by a -- service module. */ --struct nss_module_functions --{ --#undef DEFINE_NSS_FUNCTION --#define DEFINE_NSS_FUNCTION(f) nss_##f *f; --#include "function.def" --}; -- --/* Untyped version of struct nss_module_functions, for consistent -- processing purposes. */ --typedef void *nss_module_functions_untyped[sizeof (struct nss_module_functions) -- / sizeof (void *)]; -- --/* Initialization state of a NSS module. */ --enum nss_module_state --{ -- nss_module_uninitialized, -- nss_module_loaded, -- nss_module_failed, --}; -- --/* A NSS service module (potentially unloaded). Client code should -- use the functions below. */ --struct nss_module --{ -- /* Actual type is enum nss_module_state. Use int due to atomic -- access. Used in a double-checked locking idiom. */ -- int state; -- -- /* The function pointers in the module. */ -- union -- { -- struct nss_module_functions typed; -- nss_module_functions_untyped untyped; -- } functions; -- -- /* Only used for __libc_freeres unloading. */ -- void *handle; -- -- /* The next module in the list. */ -- struct nss_module *next; -- -- /* The name of the module (as it appears in /etc/nsswitch.conf). */ -- char name[]; --}; -- --/* Allocates the NSS module NAME (of NAME_LENGTH bytes) and places it -- into the global list. If it already exists in the list, return the -- pre-existing module. This does not actually load the module. -- Returns NULL on memory allocation failure. */ --struct nss_module *__nss_module_allocate (const char *name, -- size_t name_length) attribute_hidden; -- --/* Ensures that MODULE is in a loaded or failed state. */ --bool __nss_module_load (struct nss_module *module) attribute_hidden; -- --/* Ensures that MODULE is loaded and returns a pointer to the function -- NAME defined in it. Returns NULL if MODULE could not be loaded, or -- if the function NAME is not defined in the module. */ --void *__nss_module_get_function (struct nss_module *module, const char *name) -- attribute_hidden; -- --/* Block attempts to dlopen any module we haven't already opened. */ --void __nss_module_disable_loading (void); -- --/* Called from __libc_freeres. */ --void __nss_module_freeres (void) attribute_hidden; -- --#endif /* NSS_MODULE_H */ -Index: glibc-2.33/nss/nss_test.h -=================================================================== ---- glibc-2.33.orig/nss/nss_test.h -+++ glibc-2.33/nss/nss_test.h -@@ -33,12 +33,10 @@ - - #include - #include --#include - - typedef struct test_tables { - struct passwd *pwd_table; - struct group *grp_table; -- struct hostent *host_table; - } test_tables; - - extern void _nss_test1_init_hook (test_tables *) __attribute__((weak)); -@@ -46,11 +44,9 @@ extern void _nss_test2_init_hook (test_t - - #define PWD_LAST() { .pw_name = NULL, .pw_uid = 0 } - #define GRP_LAST() { .gr_name = NULL, .gr_gid = 0 } --#define HOST_LAST() { .h_name = NULL, .h_aliases = NULL, .h_length = 0, .h_addr_list = NULL } - - #define PWD_ISLAST(p) ((p)->pw_name == NULL && (p)->pw_uid == 0) - #define GRP_ISLAST(g) ((g)->gr_name == NULL && (g)->gr_gid == 0) --#define HOST_ISLAST(h) ((h)->h_name == NULL && (h)->h_length == 0) - - /* Macros to fill in the tables easily. */ - -@@ -76,11 +72,6 @@ extern void _nss_test2_init_hook (test_t - { .gr_name = (char *) n, .gr_passwd = (char *) "*", .gr_gid = u, \ - .gr_mem = (char **) m } - --#define HOST(u) \ -- { .h_name = (char *) "name" #u, .h_aliases = NULL, .h_addrtype = u, \ -- .h_length = 4, \ -- .h_addr_list = (char **) hostaddr_##u } -- - /*------------------------------------------------------------*/ - - /* Helper functions for testing passwd entries. Call -Index: glibc-2.33/nss/nss_test1.c -=================================================================== ---- glibc-2.33.orig/nss/nss_test1.c -+++ glibc-2.33/nss/nss_test1.c -@@ -66,9 +66,6 @@ static int npwd_data = default_npwd_data - static struct group *grp_data = NULL; - static int ngrp_data = 0; - --static struct hostent *host_data = NULL; --static int nhost_data = 0; -- - /* This function will get called, and once per session, look back into - the test case's executable for an init hook function, and call - it. */ -@@ -102,13 +99,6 @@ init(void) - ; - ngrp_data = i; - } -- if (t.host_table) -- { -- host_data = t.host_table; -- for (i=0; ! HOST_ISLAST(& host_data[i]); i++) -- ; -- nhost_data = i; -- } - } - initted = 1; - } -@@ -290,7 +280,7 @@ NAME(getgrent_r) (struct group *result, - ++grp_iter; - } - -- pthread_mutex_unlock (&grp_lock); -+ pthread_mutex_unlock (&pwd_lock); - - return res; - } -@@ -322,157 +312,3 @@ NAME(getgrnam_r) (const char *name, stru - - return NSS_STATUS_NOTFOUND; - } -- --/* -------------------------------------------------- */ --/* Host handling. */ -- --static size_t host_iter; --#define CURHOST host_data[host_iter] -- --static pthread_mutex_t host_lock = PTHREAD_MUTEX_INITIALIZER; -- --enum nss_status --NAME(sethostent) (int stayopen) --{ -- init(); -- host_iter = 0; -- return NSS_STATUS_SUCCESS; --} -- -- --enum nss_status --NAME(endhostent) (void) --{ -- init(); -- return NSS_STATUS_SUCCESS; --} -- --static enum nss_status --copy_host (struct hostent *result, struct hostent *local, -- char *buffer, size_t buflen, int *errnop) --{ -- struct alloc_buffer buf = alloc_buffer_create (buffer, buflen); -- char **memlist; -- int i, j; -- -- if (local->h_addr_list) -- { -- i = 0; -- while (local->h_addr_list[i]) -- ++i; -- -- memlist = alloc_buffer_alloc_array (&buf, char *, i + 1); -- -- if (memlist) { -- for (j = 0; j < i; ++j) -- memlist[j] = alloc_buffer_maybe_copy_string (&buf, local->h_addr_list[j]); -- memlist[j] = NULL; -- } -- -- result->h_addr_list = memlist; -- } -- else -- { -- result->h_addr_list = NULL; -- } -- -- result->h_aliases = NULL; -- result->h_addrtype = AF_INET; -- result->h_length = 4; -- result->h_name = alloc_buffer_maybe_copy_string (&buf, local->h_name); -- -- if (alloc_buffer_has_failed (&buf)) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- return NSS_STATUS_SUCCESS; --} -- -- --enum nss_status --NAME(gethostent_r) (struct hostent *ret, char *buffer, size_t buflen, -- struct hostent **result, int *errnop) --{ -- int res = NSS_STATUS_SUCCESS; -- -- init(); -- pthread_mutex_lock (&host_lock); -- -- if (host_iter >= nhost_data) -- { -- res = NSS_STATUS_NOTFOUND; -- *result = NULL; -- } -- else -- { -- res = copy_host (ret, &CURHOST, buffer, buflen, errnop); -- *result = ret; -- ++host_iter; -- } -- -- pthread_mutex_unlock (&host_lock); -- -- return res; --} -- --enum nss_status --NAME(gethostbyname3_r) (const char *name, int af, struct hostent *ret, -- char *buffer, size_t buflen, int *errnop, -- int *h_errnop, int32_t *ttlp, char **canonp) --{ -- init(); -- -- for (size_t idx = 0; idx < nhost_data; ++idx) -- if (strcmp (host_data[idx].h_name, name) == 0) -- return copy_host (ret, & host_data[idx], buffer, buflen, h_errnop); -- -- return NSS_STATUS_NOTFOUND; --} -- --enum nss_status --NAME(gethostbyname_r) (const char *name, struct hostent *result, -- char *buffer, size_t buflen, -- int *errnop, int *h_errnop) --{ -- return NAME(gethostbyname3_r) (name, AF_INET, result, buffer, buflen, -- errnop, h_errnop, NULL, NULL); --} -- --enum nss_status --NAME(gethostbyname2_r) (const char *name, int af, struct hostent *result, -- char *buffer, size_t buflen, -- int *errnop, int *h_errnop) --{ -- return NAME(gethostbyname3_r) (name, af, result, buffer, buflen, -- errnop, h_errnop, NULL, NULL); --} -- --enum nss_status --NAME(gethostbyaddr2_r) (const void *addr, socklen_t len, int af, -- struct hostent *result, char *buffer, size_t buflen, -- int *errnop, int *h_errnop, int32_t *ttlp) --{ -- init(); -- -- /* Support this later. */ -- if (len != 4) -- return NSS_STATUS_NOTFOUND; -- -- for (size_t idx = 0; idx < nhost_data; ++idx) -- if (memcmp (host_data[idx].h_addr, addr, len) == 0) -- return copy_host (result, & host_data[idx], buffer, buflen, h_errnop); -- -- return NSS_STATUS_NOTFOUND; --} -- --/* Note: only the first address is supported, intentionally. */ --enum nss_status --NAME(gethostbyaddr_r) (const void *addr, socklen_t len, int af, -- struct hostent *result, char *buffer, size_t buflen, -- int *errnop, int *h_errnop) --{ -- return NAME(gethostbyaddr2_r) (addr, len, af, result, buffer, buflen, -- errnop, h_errnop, NULL); --} -Index: glibc-2.33/nss/nsswitch.c -=================================================================== ---- glibc-2.33.orig/nss/nsswitch.c -+++ glibc-2.33/nss/nsswitch.c -@@ -32,7 +32,6 @@ - #include - #include - #include --#include - - #if !defined DO_STATIC_NSS || defined SHARED - # include -@@ -43,20 +42,36 @@ - #include - #include - -+/* Prototypes for the local functions. */ -+static name_database *nss_parse_file (const char *fname); -+static name_database_entry *nss_getline (char *line); -+static service_user *nss_parse_service_list (const char *line); -+#if !defined DO_STATIC_NSS || defined SHARED -+static service_library *nss_new_service (name_database *database, -+ const char *name); -+#endif -+ -+ - /* Declare external database variables. */ - #define DEFINE_DATABASE(name) \ -- nss_action_list __nss_##name##_database attribute_hidden; \ -+ service_user *__nss_##name##_database attribute_hidden; \ - weak_extern (__nss_##name##_database) - #include "databases.def" - #undef DEFINE_DATABASE - -- --#undef DEFINE_DATABASE --#define DEFINE_DATABASE(name) #name, --static const char * database_names[] = { -+/* Structure to map database name to variable. */ -+static const struct -+{ -+ const char name[10]; -+ service_user **dbp; -+} databases[] = -+{ -+#define DEFINE_DATABASE(name) \ -+ { #name, &__nss_##name##_database }, - #include "databases.def" -- NULL -+#undef DEFINE_DATABASE - }; -+#define ndatabases (sizeof (databases) / sizeof (databases[0])) - - #ifdef USE_NSCD - /* Flags whether custom rules for database is set. */ -@@ -64,36 +79,103 @@ bool __nss_database_custom[NSS_DBSIDX_ma - #endif - - --/*__libc_lock_define_initialized (static, lock)*/ -+__libc_lock_define_initialized (static, lock) -+ -+#if !defined DO_STATIC_NSS || defined SHARED -+/* String with revision number of the shared object files. */ -+static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15; -+#endif -+ -+/* The root of the whole data base. */ -+static name_database *service_table; -+ -+/* List of default service lists that were generated by glibc because -+ /etc/nsswitch.conf did not provide a value. -+ The list is only maintained so we can free such service lists in -+ __libc_freeres. */ -+static name_database_entry *defconfig_entries; -+ -+ -+#if defined USE_NSCD && (!defined DO_STATIC_NSS || defined SHARED) -+/* Nonzero if this is the nscd process. */ -+static bool is_nscd; -+/* The callback passed to the init functions when nscd is used. */ -+static void (*nscd_init_cb) (size_t, struct traced_file *); -+#endif -+ - - /* -1 == database not found - 0 == database entry pointer stored */ - int - __nss_database_lookup2 (const char *database, const char *alternate_name, -- const char *defconfig, nss_action_list *ni) -+ const char *defconfig, service_user **ni) - { -- int database_id; -+ /* Prevent multiple threads to change the service table. */ -+ __libc_lock_lock (lock); - -- for (database_id = 0; database_names[database_id]; database_id++) -- if (strcmp (database_names[database_id], database) == 0) -- break; -+ /* Reconsider database variable in case some other thread called -+ `__nss_configure_lookup' while we waited for the lock. */ -+ if (*ni != NULL) -+ { -+ __libc_lock_unlock (lock); -+ return 0; -+ } - -- if (database_names[database_id] == NULL) -- return -1; -+ /* Are we initialized yet? */ -+ if (service_table == NULL) -+ /* Read config file. */ -+ service_table = nss_parse_file (_PATH_NSSWITCH_CONF); - -- /* If *NI is NULL, the database was not mentioned in nsswitch.conf. -- If *NI is not NULL, but *NI->module is NULL, the database was in -- nsswitch.conf but listed no actions. We test for the former. */ -- if (__nss_database_get (database_id, ni) && *ni != NULL) -+ /* Test whether configuration data is available. */ -+ if (service_table != NULL) - { -- /* Success. */ -- return 0; -+ /* Return first `service_user' entry for DATABASE. */ -+ name_database_entry *entry; -+ -+ /* XXX Could use some faster mechanism here. But each database is -+ only requested once and so this might not be critical. */ -+ for (entry = service_table->entry; entry != NULL; entry = entry->next) -+ if (strcmp (database, entry->name) == 0) -+ *ni = entry->service; -+ -+ if (*ni == NULL && alternate_name != NULL) -+ /* We haven't found an entry so far. Try to find it with the -+ alternative name. */ -+ for (entry = service_table->entry; entry != NULL; entry = entry->next) -+ if (strcmp (alternate_name, entry->name) == 0) -+ *ni = entry->service; - } -- else -+ -+ /* No configuration data is available, either because nsswitch.conf -+ doesn't exist or because it doesn't have a line for this database. -+ -+ DEFCONFIG specifies the default service list for this database, -+ or null to use the most common default. */ -+ if (*ni == NULL) - { -- /* Failure. */ -- return -1; -+ *ni = nss_parse_service_list (defconfig ?: "files"); -+ if (*ni != NULL) -+ { -+ /* Record the memory we've just allocated in defconfig_entries list, -+ so we can free it later. */ -+ name_database_entry *entry; -+ -+ /* Allocate ENTRY plus size of name (1 here). */ -+ entry = (name_database_entry *) malloc (sizeof (*entry) + 1); -+ -+ if (entry != NULL) -+ { -+ entry->next = defconfig_entries; -+ entry->service = *ni; -+ entry->name[0] = '\0'; -+ defconfig_entries = entry; -+ } -+ } - } -+ -+ __libc_lock_unlock (lock); -+ -+ return *ni != NULL ? 0 : -1; - } - libc_hidden_def (__nss_database_lookup2) - -@@ -102,7 +184,7 @@ libc_hidden_def (__nss_database_lookup2) - 0 == function found - 1 == finished */ - int --__nss_lookup (nss_action_list *ni, const char *fct_name, const char *fct2_name, -+__nss_lookup (service_user **ni, const char *fct_name, const char *fct2_name, - void **fctp) - { - *fctp = __nss_lookup_function (*ni, fct_name); -@@ -111,16 +193,16 @@ __nss_lookup (nss_action_list *ni, const - - while (*fctp == NULL - && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE -- && (*ni)[1].module != NULL) -+ && (*ni)->next != NULL) - { -- ++(*ni); -+ *ni = (*ni)->next; - - *fctp = __nss_lookup_function (*ni, fct_name); - if (*fctp == NULL && fct2_name != NULL) - *fctp = __nss_lookup_function (*ni, fct2_name); - } - -- return *fctp != NULL ? 0 : (*ni)[1].module == NULL ? 1 : -1; -+ return *fctp != NULL ? 0 : (*ni)->next == NULL ? 1 : -1; - } - libc_hidden_def (__nss_lookup) - -@@ -129,7 +211,7 @@ libc_hidden_def (__nss_lookup) - 0 == adjusted for next function - 1 == finished */ - int --__nss_next2 (nss_action_list *ni, const char *fct_name, const char *fct2_name, -+__nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, - void **fctp, int status, int all_values) - { - if (all_values) -@@ -151,12 +233,12 @@ __nss_next2 (nss_action_list *ni, const - return 1; - } - -- if ((*ni)[1].module == NULL) -+ if ((*ni)->next == NULL) - return -1; - - do - { -- ++(*ni); -+ *ni = (*ni)->next; - - *fctp = __nss_lookup_function (*ni, fct_name); - if (*fctp == NULL && fct2_name != NULL) -@@ -164,17 +246,675 @@ __nss_next2 (nss_action_list *ni, const - } - while (*fctp == NULL - && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE -- && (*ni)[1].module != NULL); -+ && (*ni)->next != NULL); - - return *fctp != NULL ? 0 : -1; - } - libc_hidden_def (__nss_next2) - -+int -+__nss_configure_lookup (const char *dbname, const char *service_line) -+{ -+ service_user *new_db; -+ size_t cnt; -+ -+ for (cnt = 0; cnt < ndatabases; ++cnt) -+ { -+ int cmp = strcmp (dbname, databases[cnt].name); -+ if (cmp == 0) -+ break; -+ if (cmp < 0) -+ { -+ __set_errno (EINVAL); -+ return -1; -+ } -+ } -+ -+ if (cnt == ndatabases) -+ { -+ __set_errno (EINVAL); -+ return -1; -+ } -+ -+ /* Test whether it is really used. */ -+ if (databases[cnt].dbp == NULL) -+ /* Nothing to do, but we could do. */ -+ return 0; -+ -+ /* Try to generate new data. */ -+ new_db = nss_parse_service_list (service_line); -+ if (new_db == NULL) -+ { -+ /* Illegal service specification. */ -+ __set_errno (EINVAL); -+ return -1; -+ } -+ -+ /* Prevent multiple threads to change the service table. */ -+ __libc_lock_lock (lock); -+ -+ /* Install new rules. */ -+ *databases[cnt].dbp = new_db; -+#ifdef USE_NSCD -+ __nss_database_custom[cnt] = true; -+#endif -+ -+ __libc_lock_unlock (lock); -+ -+ return 0; -+} -+ -+ -+/* Comparison function for searching NI->known tree. */ -+static int -+known_compare (const void *p1, const void *p2) -+{ -+ return p1 == p2 ? 0 : strcmp (*(const char *const *) p1, -+ *(const char *const *) p2); -+} -+ -+ -+#if !defined DO_STATIC_NSS || defined SHARED -+/* Load library. */ -+static int -+nss_load_library (service_user *ni) -+{ -+ if (ni->library == NULL) -+ { -+ /* This service has not yet been used. Fetch the service -+ library for it, creating a new one if need be. If there -+ is no service table from the file, this static variable -+ holds the head of the service_library list made from the -+ default configuration. */ -+ static name_database default_table; -+ ni->library = nss_new_service (service_table ?: &default_table, -+ ni->name); -+ if (ni->library == NULL) -+ return -1; -+ } -+ -+ if (ni->library->lib_handle == NULL) -+ { -+ /* Load the shared library. */ -+ size_t shlen = (7 + strlen (ni->name) + 3 -+ + strlen (__nss_shlib_revision) + 1); -+ int saved_errno = errno; -+ char shlib_name[shlen]; -+ -+ /* Construct shared object name. */ -+ __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name, -+ "libnss_"), -+ ni->name), -+ ".so"), -+ __nss_shlib_revision); -+ -+ ni->library->lib_handle = __libc_dlopen (shlib_name); -+ if (ni->library->lib_handle == NULL) -+ { -+ /* Failed to load the library. */ -+ ni->library->lib_handle = (void *) -1l; -+ __set_errno (saved_errno); -+ } -+# ifdef USE_NSCD -+ else if (is_nscd) -+ { -+ /* Call the init function when nscd is used. */ -+ size_t initlen = (5 + strlen (ni->name) -+ + strlen ("_init") + 1); -+ char init_name[initlen]; -+ -+ /* Construct the init function name. */ -+ __stpcpy (__stpcpy (__stpcpy (init_name, -+ "_nss_"), -+ ni->name), -+ "_init"); -+ -+ /* Find the optional init function. */ -+ void (*ifct) (void (*) (size_t, struct traced_file *)) -+ = __libc_dlsym (ni->library->lib_handle, init_name); -+ if (ifct != NULL) -+ { -+ void (*cb) (size_t, struct traced_file *) = nscd_init_cb; -+# ifdef PTR_DEMANGLE -+ PTR_DEMANGLE (cb); -+# endif -+ ifct (cb); -+ } -+ } -+# endif -+ } -+ -+ return 0; -+} -+#endif -+ -+ - void * --__nss_lookup_function (nss_action_list ni, const char *fct_name) -+__nss_lookup_function (service_user *ni, const char *fct_name) - { -- if (ni->module == NULL) -- return NULL; -- return __nss_module_get_function (ni->module, fct_name); -+ void **found, *result; -+ -+ /* We now modify global data. Protect it. */ -+ __libc_lock_lock (lock); -+ -+ /* Search the tree of functions previously requested. Data in the -+ tree are `known_function' structures, whose first member is a -+ `const char *', the lookup key. The search returns a pointer to -+ the tree node structure; the first member of the is a pointer to -+ our structure (i.e. what will be a `known_function'); since the -+ first member of that is the lookup key string, &FCT_NAME is close -+ enough to a pointer to our structure to use as a lookup key that -+ will be passed to `known_compare' (above). */ -+ -+ found = __tsearch (&fct_name, &ni->known, &known_compare); -+ if (found == NULL) -+ /* This means out-of-memory. */ -+ result = NULL; -+ else if (*found != &fct_name) -+ { -+ /* The search found an existing structure in the tree. */ -+ result = ((known_function *) *found)->fct_ptr; -+#ifdef PTR_DEMANGLE -+ PTR_DEMANGLE (result); -+#endif -+ } -+ else -+ { -+ /* This name was not known before. Now we have a node in the tree -+ (in the proper sorted position for FCT_NAME) that points to -+ &FCT_NAME instead of any real `known_function' structure. -+ Allocate a new structure and fill it in. */ -+ -+ known_function *known = malloc (sizeof *known); -+ if (! known) -+ { -+#if !defined DO_STATIC_NSS || defined SHARED -+ remove_from_tree: -+#endif -+ /* Oops. We can't instantiate this node properly. -+ Remove it from the tree. */ -+ __tdelete (&fct_name, &ni->known, &known_compare); -+ free (known); -+ result = NULL; -+ } -+ else -+ { -+ /* Point the tree node at this new structure. */ -+ *found = known; -+ known->fct_name = fct_name; -+ -+#if !defined DO_STATIC_NSS || defined SHARED -+ /* Load the appropriate library. */ -+ if (nss_load_library (ni) != 0) -+ /* This only happens when out of memory. */ -+ goto remove_from_tree; -+ -+ if (ni->library->lib_handle == (void *) -1l) -+ /* Library not found => function not found. */ -+ result = NULL; -+ else -+ { -+ /* Get the desired function. */ -+ size_t namlen = (5 + strlen (ni->name) + 1 -+ + strlen (fct_name) + 1); -+ char name[namlen]; -+ -+ /* Construct the function name. */ -+ __stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"), -+ ni->name), -+ "_"), -+ fct_name); -+ -+ /* Look up the symbol. */ -+ result = __libc_dlsym (ni->library->lib_handle, name); -+ } -+#else -+ /* We can't get function address dynamically in static linking. */ -+ { -+# define DEFINE_ENT(h,nm) \ -+ { #h"_get"#nm"ent_r", _nss_##h##_get##nm##ent_r }, \ -+ { #h"_end"#nm"ent", _nss_##h##_end##nm##ent }, \ -+ { #h"_set"#nm"ent", _nss_##h##_set##nm##ent }, -+# define DEFINE_GET(h,nm) \ -+ { #h"_get"#nm"_r", _nss_##h##_get##nm##_r }, -+# define DEFINE_GETBY(h,nm,ky) \ -+ { #h"_get"#nm"by"#ky"_r", _nss_##h##_get##nm##by##ky##_r }, -+ static struct fct_tbl { const char *fname; void *fp; } *tp, tbl[] = -+ { -+# include "function.def" -+ { NULL, NULL } -+ }; -+ size_t namlen = (5 + strlen (ni->name) + 1 -+ + strlen (fct_name) + 1); -+ char name[namlen]; -+ -+ /* Construct the function name. */ -+ __stpcpy (__stpcpy (__stpcpy (name, ni->name), -+ "_"), -+ fct_name); -+ -+ result = NULL; -+ for (tp = &tbl[0]; tp->fname; tp++) -+ if (strcmp (tp->fname, name) == 0) -+ { -+ result = tp->fp; -+ break; -+ } -+ } -+#endif -+ -+ /* Remember function pointer for later calls. Even if null, we -+ record it so a second try needn't search the library again. */ -+ known->fct_ptr = result; -+#ifdef PTR_MANGLE -+ PTR_MANGLE (known->fct_ptr); -+#endif -+ } -+ } -+ -+ /* Remove the lock. */ -+ __libc_lock_unlock (lock); -+ -+ return result; - } - libc_hidden_def (__nss_lookup_function) -+ -+ -+static name_database * -+nss_parse_file (const char *fname) -+{ -+ FILE *fp; -+ name_database *result; -+ name_database_entry *last; -+ char *line; -+ size_t len; -+ -+ /* Open the configuration file. */ -+ fp = fopen (fname, "rce"); -+ if (fp == NULL) -+ return NULL; -+ -+ /* No threads use this stream. */ -+ __fsetlocking (fp, FSETLOCKING_BYCALLER); -+ -+ result = (name_database *) malloc (sizeof (name_database)); -+ if (result == NULL) -+ { -+ fclose (fp); -+ return NULL; -+ } -+ -+ result->entry = NULL; -+ result->library = NULL; -+ last = NULL; -+ line = NULL; -+ len = 0; -+ do -+ { -+ name_database_entry *this; -+ ssize_t n; -+ -+ n = __getline (&line, &len, fp); -+ if (n < 0) -+ break; -+ if (line[n - 1] == '\n') -+ line[n - 1] = '\0'; -+ -+ /* Because the file format does not know any form of quoting we -+ can search forward for the next '#' character and if found -+ make it terminating the line. */ -+ *__strchrnul (line, '#') = '\0'; -+ -+ /* If the line is blank it is ignored. */ -+ if (line[0] == '\0') -+ continue; -+ -+ /* Each line completely specifies the actions for a database. */ -+ this = nss_getline (line); -+ if (this != NULL) -+ { -+ if (last != NULL) -+ last->next = this; -+ else -+ result->entry = this; -+ -+ last = this; -+ } -+ } -+ while (!__feof_unlocked (fp)); -+ -+ /* Free the buffer. */ -+ free (line); -+ /* Close configuration file. */ -+ fclose (fp); -+ -+ return result; -+} -+ -+ -+/* Read the source names: -+ `( ( "[" "!"? ( "=" )+ "]" )? )*' -+ */ -+static service_user * -+nss_parse_service_list (const char *line) -+{ -+ service_user *result = NULL, **nextp = &result; -+ -+ while (1) -+ { -+ service_user *new_service; -+ const char *name; -+ -+ while (isspace (line[0])) -+ ++line; -+ if (line[0] == '\0') -+ /* No source specified. */ -+ return result; -+ -+ /* Read identifier. */ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') -+ ++line; -+ if (name == line) -+ return result; -+ -+ -+ new_service = (service_user *) malloc (sizeof (service_user) -+ + (line - name + 1)); -+ if (new_service == NULL) -+ return result; -+ -+ *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; -+ -+ /* Set default actions. */ -+ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; -+ new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; -+ new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; -+ new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; -+ new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; -+ new_service->library = NULL; -+ new_service->known = NULL; -+ new_service->next = NULL; -+ -+ while (isspace (line[0])) -+ ++line; -+ -+ if (line[0] == '[') -+ { -+ /* Read criterions. */ -+ do -+ ++line; -+ while (line[0] != '\0' && isspace (line[0])); -+ -+ do -+ { -+ int not; -+ enum nss_status status; -+ lookup_actions action; -+ -+ /* Grok ! before name to mean all statii but that one. */ -+ not = line[0] == '!'; -+ if (not) -+ ++line; -+ -+ /* Read status name. */ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' -+ && line[0] != ']') -+ ++line; -+ -+ /* Compare with known statii. */ -+ if (line - name == 7) -+ { -+ if (__strncasecmp (name, "SUCCESS", 7) == 0) -+ status = NSS_STATUS_SUCCESS; -+ else if (__strncasecmp (name, "UNAVAIL", 7) == 0) -+ status = NSS_STATUS_UNAVAIL; -+ else -+ goto finish; -+ } -+ else if (line - name == 8) -+ { -+ if (__strncasecmp (name, "NOTFOUND", 8) == 0) -+ status = NSS_STATUS_NOTFOUND; -+ else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) -+ status = NSS_STATUS_TRYAGAIN; -+ else -+ goto finish; -+ } -+ else -+ goto finish; -+ -+ while (isspace (line[0])) -+ ++line; -+ if (line[0] != '=') -+ goto finish; -+ do -+ ++line; -+ while (isspace (line[0])); -+ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' -+ && line[0] != ']') -+ ++line; -+ -+ if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) -+ action = NSS_ACTION_RETURN; -+ else if (line - name == 8 -+ && __strncasecmp (name, "CONTINUE", 8) == 0) -+ action = NSS_ACTION_CONTINUE; -+ else if (line - name == 5 -+ && __strncasecmp (name, "MERGE", 5) == 0) -+ action = NSS_ACTION_MERGE; -+ else -+ goto finish; -+ -+ if (not) -+ { -+ /* Save the current action setting for this status, -+ set them all to the given action, and reset this one. */ -+ const lookup_actions save = new_service->actions[2 + status]; -+ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; -+ new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; -+ new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; -+ new_service->actions[2 + NSS_STATUS_SUCCESS] = action; -+ new_service->actions[2 + status] = save; -+ } -+ else -+ new_service->actions[2 + status] = action; -+ -+ /* Skip white spaces. */ -+ while (isspace (line[0])) -+ ++line; -+ } -+ while (line[0] != ']'); -+ -+ /* Skip the ']'. */ -+ ++line; -+ } -+ -+ *nextp = new_service; -+ nextp = &new_service->next; -+ continue; -+ -+ finish: -+ free (new_service); -+ return result; -+ } -+} -+ -+static name_database_entry * -+nss_getline (char *line) -+{ -+ const char *name; -+ name_database_entry *result; -+ size_t len; -+ -+ /* Ignore leading white spaces. ATTENTION: this is different from -+ what is implemented in Solaris. The Solaris man page says a line -+ beginning with a white space character is ignored. We regard -+ this as just another misfeature in Solaris. */ -+ while (isspace (line[0])) -+ ++line; -+ -+ /* Recognize ` ":"'. */ -+ name = line; -+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') -+ ++line; -+ if (line[0] == '\0' || name == line) -+ /* Syntax error. */ -+ return NULL; -+ *line++ = '\0'; -+ -+ len = strlen (name) + 1; -+ -+ result = (name_database_entry *) malloc (sizeof (name_database_entry) + len); -+ if (result == NULL) -+ return NULL; -+ -+ /* Save the database name. */ -+ memcpy (result->name, name, len); -+ -+ /* Parse the list of services. */ -+ result->service = nss_parse_service_list (line); -+ -+ result->next = NULL; -+ return result; -+} -+ -+ -+#if !defined DO_STATIC_NSS || defined SHARED -+static service_library * -+nss_new_service (name_database *database, const char *name) -+{ -+ service_library **currentp = &database->library; -+ -+ while (*currentp != NULL) -+ { -+ if (strcmp ((*currentp)->name, name) == 0) -+ return *currentp; -+ currentp = &(*currentp)->next; -+ } -+ -+ /* We have to add the new service. */ -+ *currentp = (service_library *) malloc (sizeof (service_library)); -+ if (*currentp == NULL) -+ return NULL; -+ -+ (*currentp)->name = name; -+ (*currentp)->lib_handle = NULL; -+ (*currentp)->next = NULL; -+ -+ return *currentp; -+} -+#endif -+ -+ -+#if defined SHARED && defined USE_NSCD -+/* Load all libraries for the service. */ -+static void -+nss_load_all_libraries (const char *service, const char *def) -+{ -+ service_user *ni = NULL; -+ -+ if (__nss_database_lookup2 (service, NULL, def, &ni) == 0) -+ while (ni != NULL) -+ { -+ nss_load_library (ni); -+ ni = ni->next; -+ } -+} -+ -+ -+/* Called by nscd and nscd alone. */ -+void -+__nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) -+{ -+# ifdef PTR_MANGLE -+ PTR_MANGLE (cb); -+# endif -+ nscd_init_cb = cb; -+ is_nscd = true; -+ -+ /* Find all the relevant modules so that the init functions are called. */ -+ nss_load_all_libraries ("passwd", "files"); -+ nss_load_all_libraries ("group", "files"); -+ nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files"); -+ nss_load_all_libraries ("services", NULL); -+ -+ /* Disable all uses of NSCD. */ -+ __nss_not_use_nscd_passwd = -1; -+ __nss_not_use_nscd_group = -1; -+ __nss_not_use_nscd_hosts = -1; -+ __nss_not_use_nscd_services = -1; -+ __nss_not_use_nscd_netgroup = -1; -+} -+#endif -+ -+static void -+free_database_entries (name_database_entry *entry) -+{ -+ while (entry != NULL) -+ { -+ name_database_entry *olde = entry; -+ service_user *service = entry->service; -+ -+ while (service != NULL) -+ { -+ service_user *olds = service; -+ -+ if (service->known != NULL) -+ __tdestroy (service->known, free); -+ -+ service = service->next; -+ free (olds); -+ } -+ -+ entry = entry->next; -+ free (olde); -+ } -+} -+ -+/* Free all resources if necessary. */ -+libc_freeres_fn (free_defconfig) -+{ -+ name_database_entry *entry = defconfig_entries; -+ -+ if (entry == NULL) -+ /* defconfig was not used. */ -+ return; -+ -+ /* Don't disturb ongoing other threads (if there are any). */ -+ defconfig_entries = NULL; -+ -+ free_database_entries (entry); -+} -+ -+libc_freeres_fn (free_mem) -+{ -+ name_database *top = service_table; -+ service_library *library; -+ -+ if (top == NULL) -+ /* Maybe we have not read the nsswitch.conf file. */ -+ return; -+ -+ /* Don't disturb ongoing other threads (if there are any). */ -+ service_table = NULL; -+ -+ free_database_entries (top->entry); -+ -+ library = top->library; -+ while (library != NULL) -+ { -+ service_library *oldl = library; -+ -+ if (library->lib_handle && library->lib_handle != (void *) -1l) -+ __libc_dlclose (library->lib_handle); -+ -+ library = library->next; -+ free (oldl); -+ } -+ -+ free (top); -+} -Index: glibc-2.33/nss/nsswitch.h -=================================================================== ---- glibc-2.33.orig/nss/nsswitch.h -+++ glibc-2.33/nss/nsswitch.h -@@ -36,7 +36,6 @@ typedef enum - NSS_ACTION_MERGE - } lookup_actions; - --struct nss_action; - - typedef struct service_library - { -@@ -59,8 +58,42 @@ typedef struct - } known_function; - - -+typedef struct service_user -+{ -+ /* And the link to the next entry. */ -+ struct service_user *next; -+ /* Action according to result. */ -+ lookup_actions actions[5]; -+ /* Link to the underlying library object. */ -+ service_library *library; -+ /* Collection of known functions. */ -+ void *known; -+ /* Name of the service (`files', `dns', `nis', ...). */ -+ char name[0]; -+} service_user; -+ - /* To access the action based on the status value use this macro. */ --#define nss_next_action(ni, status) nss_action_get (ni, status) -+#define nss_next_action(ni, status) ((ni)->actions[2 + status]) -+ -+ -+typedef struct name_database_entry -+{ -+ /* And the link to the next entry. */ -+ struct name_database_entry *next; -+ /* List of service to be used. */ -+ service_user *service; -+ /* Name of the database. */ -+ char name[0]; -+} name_database_entry; -+ -+ -+typedef struct name_database -+{ -+ /* List of all known databases. */ -+ name_database_entry *entry; -+ /* List of libraries with service implementation. */ -+ service_library *library; -+} name_database; - - - #ifdef USE_NSCD -@@ -94,13 +127,13 @@ extern bool __nss_database_custom[NSS_DB - than one function can use the database. */ - extern int __nss_database_lookup2 (const char *database, - const char *alternative_name, -- const char *defconfig, struct nss_action **ni); -+ const char *defconfig, service_user **ni); - libc_hidden_proto (__nss_database_lookup2) - - /* Put first function with name FCT_NAME for SERVICE in FCTP. The - position is remembered in NI. The function returns a value < 0 if - an error occurred or no such function exists. */ --extern int __nss_lookup (struct nss_action **ni, const char *fct_name, -+extern int __nss_lookup (service_user **ni, const char *fct_name, - const char *fct2_name, void **fctp); - libc_hidden_proto (__nss_lookup) - -@@ -117,16 +150,16 @@ libc_hidden_proto (__nss_lookup) - services. In other words, only if all four lookup results have - the action RETURN associated the lookup process stops before the - natural end. */ --extern int __nss_next2 (struct nss_action **ni, const char *fct_name, -+extern int __nss_next2 (service_user **ni, const char *fct_name, - const char *fct2_name, void **fctp, int status, - int all_values) attribute_hidden; - libc_hidden_proto (__nss_next2) --extern int __nss_next (struct nss_action **ni, const char *fct_name, void **fctp, -+extern int __nss_next (service_user **ni, const char *fct_name, void **fctp, - int status, int all_values); - - /* Search for the service described in NI for a function named FCT_NAME - and return a pointer to this function if successful. */ --extern void *__nss_lookup_function (struct nss_action *ni, const char *fct_name); -+extern void *__nss_lookup_function (service_user *ni, const char *fct_name); - libc_hidden_proto (__nss_lookup_function) - - -@@ -136,7 +169,7 @@ struct traced_file; - extern void __nss_disable_nscd (void (*) (size_t, struct traced_file *)); - - --typedef int (*db_lookup_function) (struct nss_action **, const char *, const char *, -+typedef int (*db_lookup_function) (service_user **, const char *, const char *, - void **); - typedef enum nss_status (*setent_function) (int); - typedef enum nss_status (*endent_function) (void); -@@ -147,20 +180,20 @@ typedef int (*getent_r_function) (void * - - extern void __nss_setent (const char *func_name, - db_lookup_function lookup_fct, -- struct nss_action **nip, struct nss_action **startp, -- struct nss_action **last_nip, int stayon, -+ service_user **nip, service_user **startp, -+ service_user **last_nip, int stayon, - int *stayon_tmp, int res) - attribute_hidden; - extern void __nss_endent (const char *func_name, - db_lookup_function lookup_fct, -- struct nss_action **nip, struct nss_action **startp, -- struct nss_action **last_nip, int res) -+ service_user **nip, service_user **startp, -+ service_user **last_nip, int res) - attribute_hidden; - extern int __nss_getent_r (const char *getent_func_name, - const char *setent_func_name, - db_lookup_function lookup_fct, -- struct nss_action **nip, struct nss_action **startp, -- struct nss_action **last_nip, int *stayon_tmp, -+ service_user **nip, service_user **startp, -+ service_user **last_nip, int *stayon_tmp, - int res, - void *resbuf, char *buffer, size_t buflen, - void **result, int *h_errnop) -@@ -194,15 +227,11 @@ libc_hidden_proto (__nss_hostname_digits - - /* Prototypes for __nss_*_lookup2 functions. */ - #define DEFINE_DATABASE(arg) \ -- extern struct nss_action *__nss_##arg##_database attribute_hidden; \ -- int __nss_##arg##_lookup2 (struct nss_action **, const char *, \ -+ extern service_user *__nss_##arg##_database attribute_hidden; \ -+ int __nss_##arg##_lookup2 (service_user **, const char *, \ - const char *, void **); \ - libc_hidden_proto (__nss_##arg##_lookup2) - #include "databases.def" - #undef DEFINE_DATABASE - --#include --#include --#include -- - #endif /* nsswitch.h */ -Index: glibc-2.33/nss/tst-reload1.c -=================================================================== ---- glibc-2.33.orig/nss/tst-reload1.c -+++ /dev/null -@@ -1,341 +0,0 @@ --/* Test that nsswitch.conf reloading actually works. -- Copyright (C) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include --#include --#include --#include --#include --#include --#include -- --#include --#include -- --#include "nss_test.h" -- --/* Size of buffers used by *_r functions. */ --#define TESTBUFLEN 4096 -- --static struct passwd pwd_table_1[] = { -- PWD (100), -- PWD (30), -- PWD (200), -- PWD (60), -- PWD (20000), -- PWD_LAST () -- }; -- --static const char *hostaddr_5[] = -- { -- "ABCD", "abcd", "1234", NULL -- }; -- --static const char *hostaddr_15[] = -- { -- "4321", "ghij", NULL -- }; -- --static const char *hostaddr_25[] = -- { -- "WXYZ", NULL -- }; -- -- --static struct hostent host_table_1[] = { -- HOST (5), -- HOST (15), -- HOST (25), -- HOST_LAST () --}; -- --void --_nss_test1_init_hook(test_tables *t) --{ -- t->pwd_table = pwd_table_1; -- t->host_table = host_table_1; --} -- --/* The first of these must not appear in pwd_table_1. */ --static struct passwd pwd_table_2[] = { -- PWD (5), -- PWD_N(200, "name30"), -- PWD (16), -- PWD_LAST () -- }; -- --static const char *hostaddr_6[] = -- { -- "mnop", NULL -- }; -- --static const char *hostaddr_16[] = -- { -- "7890", "a1b2", NULL -- }; -- --static const char *hostaddr_26[] = -- { -- "qwer", "tyui", NULL -- }; -- --static struct hostent host_table_2[] = { -- HOST (6), -- HOST (16), -- HOST (26), -- HOST_LAST () --}; -- --void --_nss_test2_init_hook(test_tables *t) --{ -- t->pwd_table = pwd_table_2; -- t->host_table = host_table_2; --} -- --static void --must_be_tests (struct passwd *pt, struct hostent *ht) --{ -- int i; -- struct hostent *h; -- -- struct passwd *p; -- for (i = 0; !PWD_ISLAST (&pt[i]); ++i) -- { -- p = getpwuid (pt[i].pw_uid); -- TEST_VERIFY (p != NULL); -- if (p != NULL) -- { -- TEST_VERIFY (strcmp (p->pw_name, pt[i].pw_name) == 0); -- } -- } -- -- setpwent (); -- for (i = 0; !PWD_ISLAST (&pt[i]); ++i) -- { -- p = getpwent (); -- TEST_VERIFY (p != NULL); -- if (p != NULL) -- { -- TEST_VERIFY (strcmp (p->pw_name, pt[i].pw_name) == 0); -- TEST_VERIFY (p->pw_uid == pt[i].pw_uid); -- } -- } -- endpwent (); -- -- for (i = 0; !HOST_ISLAST (&ht[i]); ++i) -- { -- h = gethostbyname (ht[i].h_name); -- TEST_VERIFY (h != NULL); -- if (h != NULL) -- { -- TEST_VERIFY (strcmp (h->h_name, ht[i].h_name) == 0); -- TEST_VERIFY (h->h_addr_list[0] != NULL); -- if (h->h_addr_list[0]) -- TEST_VERIFY (strcmp (h->h_addr_list[0], ht[i].h_addr_list[0]) == 0); -- } -- } -- -- for (i = 0; !HOST_ISLAST (&ht[i]); ++i) -- { -- struct hostent r, *rp; -- char buf[TESTBUFLEN]; -- int herrno, res; -- -- res = gethostbyname2_r (ht[i].h_name, AF_INET, -- &r, buf, TESTBUFLEN, &rp, &herrno); -- TEST_VERIFY (res == 0); -- if (res == 0) -- { -- TEST_VERIFY (strcmp (r.h_name, ht[i].h_name) == 0); -- TEST_VERIFY (r.h_addr_list[0] != NULL); -- if (r.h_addr_list[0]) -- TEST_VERIFY (strcmp (r.h_addr_list[0], ht[i].h_addr_list[0]) == 0); -- } -- } -- -- for (i = 0; !HOST_ISLAST (&ht[i]); ++i) -- { -- h = gethostbyaddr (ht[i].h_addr, 4, AF_INET); -- TEST_VERIFY (h != NULL); -- if (h != NULL) -- { -- TEST_VERIFY (strcmp (h->h_name, ht[i].h_name) == 0); -- TEST_VERIFY (h->h_addr_list[0] != NULL); -- if (h->h_addr_list[0]) -- TEST_VERIFY (strcmp (h->h_addr_list[0], ht[i].h_addr_list[0]) == 0); -- } -- } -- -- /* getaddrinfo */ -- -- for (i = 0; !HOST_ISLAST (&ht[i]); ++i) -- { -- struct addrinfo *ap; -- struct addrinfo hint; -- int res, j; -- -- memset (&hint, 0, sizeof (hint)); -- hint.ai_family = AF_INET; -- hint.ai_socktype = SOCK_STREAM; -- hint.ai_protocol = 0; -- hint.ai_flags = 0; -- -- ap = NULL; -- res = getaddrinfo (ht[i].h_name, NULL, &hint, &ap); -- TEST_VERIFY (res == 0); -- TEST_VERIFY (ap != NULL); -- if (res == 0 && ap != NULL) -- { -- j = 0; /* which address in the list */ -- while (ap) -- { -- struct sockaddr_in *in = (struct sockaddr_in *)ap->ai_addr; -- unsigned char *up = (unsigned char *)&in->sin_addr; -- -- TEST_VERIFY (memcmp (up, ht[i].h_addr_list[j], 4) == 0); -- -- ap = ap->ai_next; -- ++j; -- } -- } -- } -- -- /* getnameinfo */ -- -- for (i = 0; !HOST_ISLAST (&ht[i]); ++i) -- { -- struct sockaddr_in addr; -- int res; -- char host_buf[NI_MAXHOST]; -- -- memset (&addr, 0, sizeof (addr)); -- addr.sin_family = AF_INET; -- addr.sin_port = 80; -- memcpy (& addr.sin_addr, ht[i].h_addr_list[0], 4); -- -- res = getnameinfo ((struct sockaddr *) &addr, sizeof(addr), -- host_buf, sizeof(host_buf), -- NULL, 0, NI_NOFQDN); -- -- TEST_VERIFY (res == 0); -- if (res == 0) -- TEST_VERIFY (strcmp (ht[i].h_name, host_buf) == 0); -- else -- printf ("error %s\n", gai_strerror (res)); -- } --} -- --static void --must_be_1 (void) --{ -- struct passwd *p; -- -- must_be_tests (pwd_table_1, host_table_1); -- p = getpwnam("name5"); -- TEST_VERIFY (p == NULL); --} -- --static void --must_be_2 (void) --{ -- struct passwd *p; -- -- must_be_tests (pwd_table_2, host_table_2); -- p = getpwnam("name100"); -- TEST_VERIFY (p == NULL); --} -- --static void --xrename (const char *a, const char *b) --{ -- int i = rename (a, b); -- if (i != 0) -- FAIL_EXIT1 ("rename(%s,%s) failed: %s\n", a, b, strerror(errno)); --} -- --/* If the actions change while in the midst of doing a series of -- lookups, make sure they're consistent. */ --static void --test_cross_switch_consistency (void) --{ -- int i; -- struct passwd *p; -- -- /* We start by initiating a set/get/end loop on conf1. */ -- setpwent (); -- for (i = 0; !PWD_ISLAST (&pwd_table_1[i]); ++i) -- { -- p = getpwent (); -- TEST_VERIFY (p != NULL); -- if (p != NULL) -- { -- TEST_VERIFY (strcmp (p->pw_name, pwd_table_1[i].pw_name) == 0); -- TEST_VERIFY (p->pw_uid == pwd_table_1[i].pw_uid); -- } -- -- /* After the first lookup, switch to conf2 and verify */ -- if (i == 0) -- { -- xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf1"); -- xrename ("/etc/nsswitch.conf2", "/etc/nsswitch.conf"); -- -- p = getpwnam (pwd_table_2[0].pw_name); -- TEST_VERIFY (p->pw_uid == pwd_table_2[0].pw_uid); -- } -- -- /* But the original loop should still be on conf1. */ -- } -- endpwent (); -- -- /* Make sure the set/get/end loop sees conf2 now. */ -- setpwent (); -- for (i = 0; !PWD_ISLAST (&pwd_table_2[i]); ++i) -- { -- p = getpwent (); -- TEST_VERIFY (p != NULL); -- if (p != NULL) -- { -- TEST_VERIFY (strcmp (p->pw_name, pwd_table_2[i].pw_name) == 0); -- TEST_VERIFY (p->pw_uid == pwd_table_2[i].pw_uid); -- } -- } -- endpwent (); -- --} -- --static int --do_test (void) --{ -- /* The test1 module was configured at program start. */ -- must_be_1 (); -- -- xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf1"); -- xrename ("/etc/nsswitch.conf2", "/etc/nsswitch.conf"); -- must_be_2 (); -- -- xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf2"); -- xrename ("/etc/nsswitch.conf1", "/etc/nsswitch.conf"); -- must_be_1 (); -- -- test_cross_switch_consistency (); -- -- return 0; --} -- --#include -Index: glibc-2.33/nss/tst-reload1.root/etc/nsswitch.conf -=================================================================== ---- glibc-2.33.orig/nss/tst-reload1.root/etc/nsswitch.conf -+++ /dev/null -@@ -1,3 +0,0 @@ --passwd: test1 --group: test1 --hosts: test1 -Index: glibc-2.33/nss/tst-reload1.root/etc/nsswitch.conf2 -=================================================================== ---- glibc-2.33.orig/nss/tst-reload1.root/etc/nsswitch.conf2 -+++ /dev/null -@@ -1,3 +0,0 @@ --passwd: test2 --group: test2 --hosts: test2 -Index: glibc-2.33/nss/tst-reload1.root/etc/services -=================================================================== ---- glibc-2.33.orig/nss/tst-reload1.root/etc/services -+++ /dev/null -@@ -1 +0,0 @@ --http 80/tcp -Index: glibc-2.33/nss/tst-reload1.root/tst-reload1.script -=================================================================== ---- glibc-2.33.orig/nss/tst-reload1.root/tst-reload1.script -+++ /dev/null -@@ -1,2 +0,0 @@ --cp $B/nss/libnss_test1.so $L/libnss_test1.so.2 --cp $B/nss/libnss_test2.so $L/libnss_test2.so.2 -Index: glibc-2.33/nss/tst-reload2.c -=================================================================== ---- glibc-2.33.orig/nss/tst-reload2.c -+++ /dev/null -@@ -1,130 +0,0 @@ --/* Test that reloading is disabled after a chroot. -- Copyright (C) 2020-2021 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include -- --#include "nss_test.h" -- --#ifndef PATH_MAX --# define PATH_MAX 1024 --#endif -- --static struct passwd pwd_table1[] = -- { -- PWD_N (1234, "test1"), -- PWD_N (4321, "test2"), -- PWD_LAST () -- }; -- --static const char *group_4[] = { -- "alpha", "beta", "gamma", "fred", NULL --}; -- --static struct group group_table_data[] = -- { -- GRP (4), -- GRP_LAST () -- }; -- --void --_nss_test1_init_hook (test_tables *t) --{ -- t->pwd_table = pwd_table1; -- t->grp_table = group_table_data; --} -- --static struct passwd pwd_table2[] = -- { -- PWD_N (5, "test1"), -- PWD_N (2468, "test2"), -- PWD_LAST () -- }; -- --void --_nss_test2_init_hook (test_tables *t) --{ -- t->pwd_table = pwd_table2; --} -- --static int --do_test (void) --{ -- struct passwd *pw; -- struct group *gr; -- char buf1[PATH_MAX]; -- char buf2[PATH_MAX]; -- -- sprintf (buf1, "/subdir%s", support_slibdir_prefix); -- xmkdirp (buf1, 0777); -- -- /* Copy this DSO into the chroot so it *could* be loaded. */ -- sprintf (buf1, "%s/libnss_files.so.2", support_slibdir_prefix); -- sprintf (buf2, "/subdir%s/libnss_files.so.2", support_slibdir_prefix); -- support_copy_file (buf1, buf2); -- -- /* Check we're using the "outer" nsswitch.conf. */ -- -- /* This uses the test1 DSO. */ -- pw = getpwnam ("test1"); -- TEST_VERIFY (pw != NULL); -- if (pw) -- TEST_COMPARE (pw->pw_uid, 1234); -- -- /* This just loads the test2 DSO. */ -- gr = getgrnam ("name4"); -- -- /* Change the root dir. */ -- -- TEST_VERIFY (chroot ("/subdir") == 0); -- chdir ("/"); -- -- /* Check we're NOT using the "inner" nsswitch.conf. */ -- -- /* Both DSOs are loaded, which is used? */ -- pw = getpwnam ("test2"); -- TEST_VERIFY (pw != NULL); -- if (pw) -- TEST_VERIFY (pw->pw_uid != 2468); -- -- /* The "files" DSO should not be loaded. */ -- gr = getgrnam ("test3"); -- TEST_VERIFY (gr == NULL); -- -- /* We should still be using the old configuration. */ -- pw = getpwnam ("test1"); -- TEST_VERIFY (pw != NULL); -- if (pw) -- TEST_COMPARE (pw->pw_uid, 1234); -- -- return 0; --} -- --#include -Index: glibc-2.33/nss/tst-reload2.root/etc/nsswitch.conf -=================================================================== ---- glibc-2.33.orig/nss/tst-reload2.root/etc/nsswitch.conf -+++ /dev/null -@@ -1,2 +0,0 @@ --passwd: test1 --group: test2 -Index: glibc-2.33/nss/tst-reload2.root/subdir/etc/group -=================================================================== ---- glibc-2.33.orig/nss/tst-reload2.root/subdir/etc/group -+++ /dev/null -@@ -1 +0,0 @@ --test3:x:123: -Index: glibc-2.33/nss/tst-reload2.root/subdir/etc/nsswitch.conf -=================================================================== ---- glibc-2.33.orig/nss/tst-reload2.root/subdir/etc/nsswitch.conf -+++ /dev/null -@@ -1,2 +0,0 @@ --passwd: test2 --group: files -Index: glibc-2.33/nss/tst-reload2.root/tst-reload2.script -=================================================================== ---- glibc-2.33.orig/nss/tst-reload2.root/tst-reload2.script -+++ /dev/null -@@ -1,3 +0,0 @@ --su --cp $B/nss/libnss_test1.so $L/libnss_test1.so.2 --cp $B/nss/libnss_test2.so $L/libnss_test2.so.2 -Index: glibc-2.33/posix/tst-rfc3484-2.c -=================================================================== ---- glibc-2.33.orig/posix/tst-rfc3484-2.c -+++ glibc-2.33/posix/tst-rfc3484-2.c -@@ -58,7 +58,7 @@ _res_hconf_init (void) - #undef USE_NSCD - #include "../sysdeps/posix/getaddrinfo.c" - --nss_action_list __nss_hosts_database attribute_hidden; -+service_user *__nss_hosts_database attribute_hidden; - - /* This is the beginning of the real test code. The above defines - (among other things) the function rfc3484_sort. */ -Index: glibc-2.33/posix/tst-rfc3484-3.c -=================================================================== ---- glibc-2.33.orig/posix/tst-rfc3484-3.c -+++ glibc-2.33/posix/tst-rfc3484-3.c -@@ -58,7 +58,7 @@ _res_hconf_init (void) - #undef USE_NSCD - #include "../sysdeps/posix/getaddrinfo.c" - --nss_action_list __nss_hosts_database attribute_hidden; -+service_user *__nss_hosts_database attribute_hidden; - - /* This is the beginning of the real test code. The above defines - (among other things) the function rfc3484_sort. */ -Index: glibc-2.33/posix/tst-rfc3484.c -=================================================================== ---- glibc-2.33.orig/posix/tst-rfc3484.c -+++ glibc-2.33/posix/tst-rfc3484.c -@@ -58,7 +58,7 @@ _res_hconf_init (void) - #undef USE_NSCD - #include "../sysdeps/posix/getaddrinfo.c" - --nss_action_list __nss_hosts_database attribute_hidden; -+service_user *__nss_hosts_database attribute_hidden; - - /* This is the beginning of the real test code. The above defines - (among other things) the function rfc3484_sort. */ -Index: glibc-2.33/sunrpc/netname.c -=================================================================== ---- glibc-2.33.orig/sunrpc/netname.c -+++ glibc-2.33/sunrpc/netname.c -@@ -145,7 +145,9 @@ int - netname2user (const char *netname, uid_t * uidp, gid_t * gidp, - int *gidlenp, gid_t * gidlist) - { -- nss_action_list nip; -+ static service_user *startp; -+ static netname2user_function start_fct; -+ service_user *nip; - union - { - netname2user_function f; -@@ -154,7 +156,22 @@ netname2user (const char *netname, uid_t - enum nss_status status = NSS_STATUS_UNAVAIL; - int no_more; - -- no_more = __nss_publickey_lookup2 (&nip, "netname2user", NULL, &fct.ptr); -+ if (startp == NULL) -+ { -+ no_more = __nss_publickey_lookup2 (&nip, "netname2user", NULL, &fct.ptr); -+ if (no_more) -+ startp = (service_user *) - 1; -+ else -+ { -+ startp = nip; -+ start_fct = fct.f; -+ } -+ } -+ else -+ { -+ fct.f = start_fct; -+ no_more = (nip = startp) == (service_user *) - 1; -+ } - - while (!no_more) - { -Index: glibc-2.33/sunrpc/publickey.c -=================================================================== ---- glibc-2.33.orig/sunrpc/publickey.c -+++ glibc-2.33/sunrpc/publickey.c -@@ -34,7 +34,9 @@ typedef int (*secret_function) (const ch - int - getpublickey (const char *name, char *key) - { -- nss_action_list nip; -+ static service_user *startp; -+ static public_function start_fct; -+ service_user *nip; - union - { - public_function f; -@@ -43,7 +45,22 @@ getpublickey (const char *name, char *ke - enum nss_status status = NSS_STATUS_UNAVAIL; - int no_more; - -- no_more = __nss_publickey_lookup2 (&nip, "getpublickey", NULL, &fct.ptr); -+ if (startp == NULL) -+ { -+ no_more = __nss_publickey_lookup2 (&nip, "getpublickey", NULL, &fct.ptr); -+ if (no_more) -+ startp = (service_user *) -1; -+ else -+ { -+ startp = nip; -+ start_fct = fct.f; -+ } -+ } -+ else -+ { -+ fct.f = start_fct; -+ no_more = (nip = startp) == (service_user *) -1; -+ } - - while (! no_more) - { -@@ -60,7 +77,9 @@ libc_hidden_nolink_sunrpc (getpublickey, - int - getsecretkey (const char *name, char *key, const char *passwd) - { -- nss_action_list nip; -+ static service_user *startp; -+ static secret_function start_fct; -+ service_user *nip; - union - { - secret_function f; -@@ -69,7 +88,22 @@ getsecretkey (const char *name, char *ke - enum nss_status status = NSS_STATUS_UNAVAIL; - int no_more; - -- no_more = __nss_publickey_lookup2 (&nip, "getsecretkey", NULL, &fct.ptr); -+ if (startp == NULL) -+ { -+ no_more = __nss_publickey_lookup2 (&nip, "getsecretkey", NULL, &fct.ptr); -+ if (no_more) -+ startp = (service_user *) -1; -+ else -+ { -+ startp = nip; -+ start_fct = fct.f; -+ } -+ } -+ else -+ { -+ fct.f = start_fct; -+ no_more = (nip = startp) == (service_user *) -1; -+ } - - while (! no_more) - { -Index: glibc-2.33/sysdeps/mach/hurd/fork.c -=================================================================== ---- glibc-2.33.orig/sysdeps/mach/hurd/fork.c -+++ glibc-2.33/sysdeps/mach/hurd/fork.c -@@ -28,7 +28,6 @@ - #include "hurdmalloc.h" /* XXX */ - #include - #include --#include - - #undef __fork - -@@ -69,7 +68,6 @@ __fork (void) - size_t i; - error_t err; - struct hurd_sigstate *volatile ss; -- struct nss_database_data nss_database_data; - - RUN_HOOK (_hurd_atfork_prepare_hook, ()); - -@@ -111,9 +109,6 @@ __fork (void) - /* Run things that prepare for forking before we create the task. */ - RUN_HOOK (_hurd_fork_prepare_hook, ()); - -- call_function_static_weak (__nss_database_fork_prepare_parent, -- &nss_database_data); -- - /* Lock things that want to be locked before we fork. */ - { - void *const *p; -@@ -671,9 +666,6 @@ __fork (void) - _hurd_malloc_fork_child (); - call_function_static_weak (__malloc_fork_unlock_child); - -- call_function_static_weak (__nss_database_fork_subprocess, -- &nss_database_data); -- - /* Run things that want to run in the child task to set up. */ - RUN_HOOK (_hurd_fork_child_hook, ()); - -Index: glibc-2.33/sysdeps/nptl/fork.c -=================================================================== ---- glibc-2.33.orig/sysdeps/nptl/fork.c -+++ glibc-2.33/sysdeps/nptl/fork.c -@@ -32,7 +32,6 @@ - #include - #include - #include --#include - - static void - fresetlockfiles (void) -@@ -58,8 +57,6 @@ __libc_fork (void) - - __run_fork_handlers (atfork_run_prepare, multiple_threads); - -- struct nss_database_data nss_database_data; -- - /* If we are not running multiple threads, we do not have to - preserve lock state. If fork runs from a signal handler, only - async-signal-safe functions can be used in the child. These data -@@ -67,9 +64,6 @@ __libc_fork (void) - not matter if fork was called from a signal handler. */ - if (multiple_threads) - { -- call_function_static_weak (__nss_database_fork_prepare_parent, -- &nss_database_data); -- - _IO_list_lock (); - - /* Acquire malloc locks. This needs to come last because fork -@@ -124,9 +118,6 @@ __libc_fork (void) - - /* Reset locks in the I/O code. */ - _IO_list_resetlock (); -- -- call_function_static_weak (__nss_database_fork_subprocess, -- &nss_database_data); - } - - /* Reset the lock the dynamic loader uses to protect its data. */ -Index: glibc-2.33/sysdeps/posix/getaddrinfo.c -=================================================================== ---- glibc-2.33.orig/sysdeps/posix/getaddrinfo.c -+++ glibc-2.33/sysdeps/posix/getaddrinfo.c -@@ -307,7 +307,7 @@ convert_hostent_to_gaih_addrtuple (const - memory allocation failure. The returned string is allocated on the - heap; the caller has to free it. */ - static char * --getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name) -+getcanonname (service_user *nip, struct gaih_addrtuple *at, const char *name) - { - nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r"); - char *s = (char *) name; -@@ -538,7 +538,7 @@ gaih_inet (const char *name, const struc - struct gaih_addrtuple **pat = &at; - int no_data = 0; - int no_inet6_data = 0; -- nss_action_list nip; -+ service_user *nip; - enum nss_status inet6_status = NSS_STATUS_UNAVAIL; - enum nss_status status = NSS_STATUS_UNAVAIL; - int no_more; -@@ -720,9 +720,13 @@ gaih_inet (const char *name, const struc - } - #endif - -- no_more = __nss_database_lookup2 ("hosts", NULL, -- "dns [!UNAVAIL=return] files", -- &nip); -+ if (__nss_hosts_database == NULL) -+ no_more = __nss_database_lookup2 ("hosts", NULL, -+ "dns [!UNAVAIL=return] files", -+ &__nss_hosts_database); -+ else -+ no_more = 0; -+ nip = __nss_hosts_database; - - /* If we are looking for both IPv4 and IPv6 address we don't - want the lookup functions to automatically promote IPv4 -@@ -901,9 +905,10 @@ gaih_inet (const char *name, const struc - if (nss_next_action (nip, status) == NSS_ACTION_RETURN) - break; - -- nip++; -- if (nip->module == NULL) -+ if (nip->next == NULL) - no_more = -1; -+ else -+ nip = nip->next; - } - - __resolv_context_put (res_ctx); diff --git a/x86-isa-level.patch b/x86-isa-level.patch new file mode 100644 index 0000000..28eb9cb --- /dev/null +++ b/x86-isa-level.patch @@ -0,0 +1,183 @@ +From ee9f98d9cac12e843ca59c6e4d4b225f58a66727 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Tue, 2 Feb 2021 13:45:58 -0800 +Subject: [PATCH] x86: Set minimum x86-64 level marker [BZ #27318] + +Since the full ISA set used in an ELF binary is unknown to compiler, +an x86-64 ISA level marker indicates the minimum, not maximum, ISA set +required to run such an ELF binary. We never guarantee a library with +an x86-64 ISA level v3 marker doesn't contain other ISAs beyond x86-64 +ISA level v3, like AVX VNNI. We check the x86-64 ISA level marker for +the minimum ISA set. Since -march=sandybridge enables only some ISAs +in x86-64 ISA level v3, we should set the needed ISA marker to v2. +Otherwise, libc is compiled with -march=sandybridge will fail to run on +Sandy Bridge: + +$ ./elf/ld.so ./libc.so +./libc.so: (p) CPU ISA level is lower than required: needed: 7; got: 3 + +Set the minimum, instead of maximum, x86-64 ISA level marker should have +no impact on the glibc-hwcaps directory assignment logic in ldconfig nor +ld.so. + +(cherry picked from commit 339bf918ea4830fb35614632e96f3aab3237adce) +--- + config.h.in | 6 ++++++ + sysdeps/x86/configure | 28 ++++++++++++++++++++++++++++ + sysdeps/x86/configure.ac | 16 ++++++++++++++++ + sysdeps/x86/isa-level.c | 25 ++++++++++++++----------- + 4 files changed, 64 insertions(+), 11 deletions(-) + +Index: glibc-2.33/config.h.in +=================================================================== +--- glibc-2.33.orig/config.h.in ++++ glibc-2.33/config.h.in +@@ -275,4 +275,10 @@ + /* Define if x86 ISA level should be included in shared libraries. */ + #undef INCLUDE_X86_ISA_LEVEL + ++/* Define if -msahf is enabled by default on x86. */ ++#undef HAVE_X86_LAHF_SAHF ++ ++/* Define if -mmovbe is enabled by default on x86. */ ++#undef HAVE_X86_MOVBE ++ + #endif +Index: glibc-2.33/sysdeps/x86/configure +=================================================================== +--- glibc-2.33.orig/sysdeps/x86/configure ++++ glibc-2.33/sysdeps/x86/configure +@@ -126,6 +126,8 @@ cat > conftest2.S <&5 + (eval $ac_try) 2>&5 +@@ -135,6 +137,24 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS + count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l` + if test "$count" = 1; then + libc_cv_include_x86_isa_level=yes ++ cat > conftest.c <&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } | grep -q "\-msahf"; then ++ libc_cv_have_x86_lahf_sahf=yes ++ fi ++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } | grep -q "\-mmovbe"; then ++ libc_cv_have_x86_movbe=yes ++ fi + fi + fi + rm -f conftest* +@@ -145,5 +165,13 @@ if test $libc_cv_include_x86_isa_level = + $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h + + fi ++if test $libc_cv_have_x86_lahf_sahf = yes; then ++ $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h ++ ++fi ++if test $libc_cv_have_x86_movbe = yes; then ++ $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h ++ ++fi + config_vars="$config_vars + enable-x86-isa-level = $libc_cv_include_x86_isa_level" +Index: glibc-2.33/sysdeps/x86/configure.ac +=================================================================== +--- glibc-2.33.orig/sysdeps/x86/configure.ac ++++ glibc-2.33/sysdeps/x86/configure.ac +@@ -98,14 +98,30 @@ cat > conftest2.S < conftest.c <