SHA256
3
0
forked from pool/glibc
glibc/nss-revert-api.patch
Andreas Schwab b855cdeb01 Accepting request 876230 from home:Andreas_Schwab:Factory
- Disable x86 ISA level for now (bsc#1182522, BZ #27318)
- nss-revert-api.patch: Workaround for nss-compat brokeness (bsc#1182247,
  BZ #27416)

OBS-URL: https://build.opensuse.org/request/show/876230
OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=583
2021-03-02 13:18:55 +00:00

4610 lines
136 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
- <https://www.gnu.org/licenses/>. */
-
-#include <nss.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <grp.h>
-
-#include <support/support.h>
-#include <support/check.h>
-
-/* 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<n; i++)
- TEST_COMPARE (mygroups[i], expected_groups[i]);
-
- return 0;
-}
-
-#include <support/test-driver.c>
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
- <https://www.gnu.org/licenses/>. */
-
-#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 <set-hooks.h>
#include <libc-internal.h>
-#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 <check_native.c>
/* 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
<https://www.gnu.org/licenses/>. */
-/* 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
- <https://www.gnu.org/licenses/>. */
-
-#include <nsswitch.h>
-
-#include <string.h>
-#include <libc-lock.h>
-
-/* 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
- <https://www.gnu.org/licenses/>. */
-
-#ifndef _NSS_ACTION_H
-#define _NSS_ACTION_H
-
-#include <stddef.h>
-
-/* 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
- <https://www.gnu.org/licenses/>. */
-
-#include <nsswitch.h>
-
-#include <ctype.h>
-#include <string.h>
-#include <stdbool.h>
-
-/* Staging area during parsing. */
-#define DYNARRAY_STRUCT action_list
-#define DYNARRAY_ELEMENT struct nss_action
-#define DYNARRAY_PREFIX action_list_
-#include <malloc/dynarray-skeleton.c>
-
-/* Skip whitespace in line[]. */
-#define SKIP_WS() \
- while (line[0] != '\0' && isspace (line[0])) \
- ++line;
-
-/* Read the source names:
- `( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*'
- */
-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 <source> 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
- <https://www.gnu.org/licenses/>. */
-
-#include "nss_database.h"
-
-#include <allocate_once.h>
-#include <array_length.h>
-#include <assert.h>
-#include <atomic.h>
-#include <ctype.h>
-#include <file_change_detection.h>
-#include <libc-lock.h>
-#include <netdb.h>
-#include <stdio_ext.h>
-#include <string.h>
-
-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 `<database> ":"'. */
- 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
- <https://www.gnu.org/licenses/>. */
-
-#ifndef _NSS_DATABASE_H
-#define _NSS_DATABASE_H
-
-#include <file_change_detection.h>
-
-/* 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
- <https://www.gnu.org/licenses/>. */
-
-#include <nsswitch.h>
-#include <nscd/nscd.h>
-#include <nscd/nscd_proto.h>
-
-#include <array_length.h>
-#include <assert.h>
-#include <atomic.h>
-#include <dlfcn.h>
-#include <gnu/lib-names.h>
-#include <libc-lock.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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
- <https://www.gnu.org/licenses/>. */
-
-#ifndef _NSS_MODULE_H
-#define _NSS_MODULE_H
-
-#include <nss.h>
-#include <stdbool.h>
-
-/* 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 <pwd.h>
#include <grp.h>
-#include <netdb.h>
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 <netinet/ether.h>
#include <pwd.h>
#include <shadow.h>
-#include <unistd.h>
#if !defined DO_STATIC_NSS || defined SHARED
# include <gnu/lib-names.h>
@@ -43,20 +42,36 @@
#include <sysdep.h>
#include <config.h>
+/* 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:
+ `( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*'
+ */
+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 <source> 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 `<database> ":"'. */
+ 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 <nss/nss_module.h>
-#include <nss/nss_action.h>
-#include <nss/nss_database.h>
-
#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
- <https://www.gnu.org/licenses/>. */
-
-#include <nss.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <pwd.h>
-
-#include <support/support.h>
-#include <support/check.h>
-
-#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 <support/test-driver.c>
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
- <https://www.gnu.org/licenses/>. */
-
-#include <nss.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <unistd.h>
-
-#include <support/support.h>
-#include <support/check.h>
-#include <support/xunistd.h>
-
-#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 <support/test-driver.c>
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 <tls.h>
#include <malloc/malloc-internal.h>
-#include <nss/nss_database.h>
#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 <arch-fork.h>
#include <futex-internal.h>
#include <malloc/malloc-internal.h>
-#include <nss/nss_database.h>
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);