[PATCH] nscd: Fix most data races in client retry counters (bug 33654)

Florian Weimer fweimer@redhat.com
Thu Nov 20 12:16:59 GMT 2025


Merge the individual __nss_not_use_nscd_* variables and the
__nss_database_custom variable into a new __nscd_skip_counters variable
that serves both purposes.  Unify the database counter checks and
updates into a separate function, __nscd_use_database.  Individual
client functions now call __nscd_defer_database to defer nscd use on
certain errors.  To disable nscd for databases due to custom
configuration, __nscd_disable_database can be used.

This partially fixes bug 33654 because __nscd_use_database uses atomic
updates.

---
 nscd/Makefile                |  6 ++++-
 nscd/nscd_getai.c            | 10 +++-----
 nscd/nscd_getgr_r.c          |  6 ++---
 nscd/nscd_gethst_r.c         | 10 ++++----
 nscd/nscd_getpw_r.c          |  6 ++---
 nscd/nscd_getserv_r.c        |  7 ++----
 nscd/nscd_initgroups.c       |  5 ++--
 nscd/nscd_netgroup.c         | 11 ++++-----
 nscd/nscd_proto.h            | 21 +++++++++++-----
 nscd/nscd_use_database.c     | 57 ++++++++++++++++++++++++++++++++++++++++++++
 nscd/tst-nscd_use_database.c | 53 ++++++++++++++++++++++++++++++++++++++++
 nss/getXXbyYY_r.c            | 10 ++------
 nss/getaddrinfo.c            | 12 ++++------
 nss/getnetgrent_r.c          | 14 ++---------
 nss/initgroups.c             |  9 +------
 nss/nss_database.c           |  5 +++-
 nss/nss_module.c             |  7 ++----
 nss/nsswitch.c               |  5 ----
 nss/nsswitch.h               |  2 --
 19 files changed, 166 insertions(+), 90 deletions(-)

diff --git a/nscd/Makefile b/nscd/Makefile
index b6d7bd1cb5..f54b3bcbfc 100644
--- a/nscd/Makefile
+++ b/nscd/Makefile
@@ -24,8 +24,12 @@ include ../Makeconfig
 
 ifneq ($(use-nscd),no)
 routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
-	    nscd_initgroups nscd_getserv_r nscd_netgroup
+	    nscd_initgroups nscd_getserv_r nscd_netgroup nscd_use_database
 aux	:= nscd_helper
+
+tests-internal += \
+  tst-nscd_use_database \
+  # tests
 endif
 
 # To find xmalloc.c
diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c
index 465e728fe4..b381a06695 100644
--- a/nscd/nscd_getai.c
+++ b/nscd/nscd_getai.c
@@ -27,10 +27,6 @@
 #include "nscd_proto.h"
 
 
-/* Define in nscd_gethst_r.c.  */
-extern int __nss_not_use_nscd_hosts;
-
-
 /* We use the mapping from nscd_gethst.  */
 libc_locked_map_ptr (extern, __hst_map_handle) attribute_hidden;
 
@@ -47,7 +43,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
 	__nss_have_localdomain = getenv ("LOCALDOMAIN") != NULL ? 1 : -1;
       if (__nss_have_localdomain > 0)
 	{
-	  __nss_not_use_nscd_hosts = 1;
+	  __nscd_defer_database (NSS_DBSIDX_hosts);
 	  return -1;
 	}
     }
@@ -98,7 +94,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
       if (sock == -1)
 	{
 	  /* nscd not running or wrong version.  */
-	  __nss_not_use_nscd_hosts = 1;
+	  __nscd_defer_database (NSS_DBSIDX_hosts);
 	  goto out;
 	}
     }
@@ -173,7 +169,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
       if (__glibc_unlikely (ai_resp.found == -1))
 	{
 	  /* The daemon does not cache this database.  */
-	  __nss_not_use_nscd_hosts = 1;
+	  __nscd_defer_database (NSS_DBSIDX_hosts);
 	  goto out_close;
 	}
 
diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c
index 39b9fec2f1..173fadbd97 100644
--- a/nscd/nscd_getgr_r.c
+++ b/nscd/nscd_getgr_r.c
@@ -35,8 +35,6 @@
 #include "nscd-client.h"
 #include "nscd_proto.h"
 
-int __nss_not_use_nscd_group;
-
 static int nscd_getgr_r (const char *key, size_t keylen, request_type type,
 			 struct group *resultbuf, char *buffer,
 			 size_t buflen, struct group **result);
@@ -135,7 +133,7 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
 				 sizeof (gr_resp));
       if (sock == -1)
 	{
-	  __nss_not_use_nscd_group = 1;
+	  __nscd_defer_database (NSS_DBSIDX_group);
 	  goto out;
 	}
     }
@@ -146,7 +144,7 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
   if (__glibc_unlikely (gr_resp.found == -1))
     {
       /* The daemon does not cache this database.  */
-      __nss_not_use_nscd_group = 1;
+      __nscd_defer_database (NSS_DBSIDX_group);
       goto out_close;
     }
 
diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
index 5f3eab2f4d..c4fd0906a2 100644
--- a/nscd/nscd_gethst_r.c
+++ b/nscd/nscd_gethst_r.c
@@ -26,8 +26,6 @@
 #include "nscd-client.h"
 #include "nscd_proto.h"
 
-int __nss_not_use_nscd_hosts;
-
 static int nscd_gethst_r (const char *key, size_t keylen, request_type type,
 			  struct hostent *resultbuf, char *buffer,
 			  size_t buflen, struct hostent **result,
@@ -97,7 +95,7 @@ uint32_t
 __nscd_get_nl_timestamp (void)
 {
   uint32_t retval;
-  if (__nss_not_use_nscd_hosts != 0)
+  if (!__nscd_use_database (NSS_DBSIDX_hosts))
     return 0;
 
   /* __nscd_get_mapping can change hst_map_handle.mapped to NO_MAPPING.
@@ -141,7 +139,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 	__nss_have_localdomain = getenv ("LOCALDOMAIN") != NULL ? 1 : -1;
       if (__nss_have_localdomain > 0)
 	{
-	  __nss_not_use_nscd_hosts = 1;
+	  __nscd_defer_database (NSS_DBSIDX_hosts);
 	  return -1;
 	}
     }
@@ -217,7 +215,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
 				 sizeof (hst_resp));
       if (sock == -1)
 	{
-	  __nss_not_use_nscd_hosts = 1;
+	  __nscd_defer_database (NSS_DBSIDX_hosts);
 	  goto out;
 	}
     }
@@ -228,7 +226,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
   if (__glibc_unlikely (hst_resp.found == -1))
     {
       /* The daemon does not cache this database.  */
-      __nss_not_use_nscd_hosts = 1;
+      __nscd_defer_database (NSS_DBSIDX_hosts);
       goto out_close;
     }
 
diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c
index 094770f536..cf02a51100 100644
--- a/nscd/nscd_getpw_r.c
+++ b/nscd/nscd_getpw_r.c
@@ -33,8 +33,6 @@
 #include "nscd-client.h"
 #include "nscd_proto.h"
 
-int __nss_not_use_nscd_passwd;
-
 static int nscd_getpw_r (const char *key, size_t keylen, request_type type,
 			 struct passwd *resultbuf, char *buffer,
 			 size_t buflen, struct passwd **result);
@@ -124,7 +122,7 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type,
 				 sizeof (pw_resp));
       if (sock == -1)
 	{
-	  __nss_not_use_nscd_passwd = 1;
+	  __nscd_defer_database (NSS_DBSIDX_passwd);
 	  goto out;
 	}
     }
@@ -135,7 +133,7 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type,
   if (__glibc_unlikely (pw_resp.found == -1))
     {
       /* The daemon does not cache this database.  */
-      __nss_not_use_nscd_passwd = 1;
+      __nscd_defer_database (NSS_DBSIDX_passwd);
       goto out_close;
     }
 
diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c
index b23afaf8a1..f50dbe574d 100644
--- a/nscd/nscd_getserv_r.c
+++ b/nscd/nscd_getserv_r.c
@@ -26,9 +26,6 @@
 #include "nscd_proto.h"
 
 
-int __nss_not_use_nscd_services;
-
-
 static int nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 			   request_type type, struct servent *resultbuf,
 			   char *buf, size_t buflen, struct servent **result);
@@ -179,7 +176,7 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
 				 sizeof (serv_resp));
       if (sock == -1)
 	{
-	  __nss_not_use_nscd_services = 1;
+	  __nscd_defer_database (NSS_DBSIDX_services);
 	  goto out;
 	}
     }
@@ -190,7 +187,7 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
   if (__glibc_unlikely (serv_resp.found == -1))
     {
       /* The daemon does not cache this database.  */
-      __nss_not_use_nscd_services = 1;
+      __nscd_defer_database (NSS_DBSIDX_services);
       goto out_close;
     }
 
diff --git a/nscd/nscd_initgroups.c b/nscd/nscd_initgroups.c
index 48bf597d1c..e0aae79089 100644
--- a/nscd/nscd_initgroups.c
+++ b/nscd/nscd_initgroups.c
@@ -16,6 +16,7 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <assert.h>
+#include <atomic.h>
 #include <errno.h>
 #include <grp.h>
 #include <stdlib.h>
@@ -83,7 +84,7 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
       if (sock == -1)
 	{
 	  /* nscd not running or wrong version.  */
-	  __nss_not_use_nscd_group = 1;
+	  atomic_store_relaxed (&__nscd_skip_counters[NSS_DBSIDX_group], 1);
 	  goto out;
 	}
     }
@@ -132,7 +133,7 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size,
       if (__glibc_unlikely (initgr_resp.found == -1))
 	{
 	  /* The daemon does not cache this database.  */
-	  __nss_not_use_nscd_group = 1;
+	  atomic_store_relaxed (&__nscd_skip_counters[NSS_DBSIDX_group], 1);
 	  goto out_close;
 	}
 
diff --git a/nscd/nscd_netgroup.c b/nscd/nscd_netgroup.c
index dd8f9da49b..2ea76c8722 100644
--- a/nscd/nscd_netgroup.c
+++ b/nscd/nscd_netgroup.c
@@ -24,9 +24,6 @@
 #include "nscd-client.h"
 #include "nscd_proto.h"
 
-int __nss_not_use_nscd_netgroup;
-
-
 libc_locked_map_ptr (static, map_handle);
 /* Note that we only free the structure if necessary.  The memory
    mapping is not removed since it is not visible to the malloc
@@ -87,7 +84,7 @@ __nscd_setnetgrent (const char *group, struct __netgrent *datap)
       if (sock == -1)
 	{
 	  /* nscd not running or wrong version.  */
-	  __nss_not_use_nscd_netgroup = 1;
+	  __nscd_defer_database (NSS_DBSIDX_netgroup);
 	  goto out;
 	}
     }
@@ -127,7 +124,7 @@ __nscd_setnetgrent (const char *group, struct __netgrent *datap)
       if (__glibc_unlikely (netgroup_resp.found == -1))
 	{
 	  /* The daemon does not cache this database.  */
-	  __nss_not_use_nscd_netgroup = 1;
+	  __nscd_defer_database (NSS_DBSIDX_netgroup);
 	  goto out_close;
 	}
 
@@ -239,7 +236,7 @@ __nscd_innetgr (const char *netgroup, const char *host, const char *user,
   if (sock == -1)
     {
       /* nscd not running or wrong version.  */
-      __nss_not_use_nscd_netgroup = 1;
+      __nscd_defer_database (NSS_DBSIDX_netgroup);
       goto out;
     }
 
@@ -251,7 +248,7 @@ __nscd_innetgr (const char *netgroup, const char *host, const char *user,
       if (__glibc_unlikely (innetgroup_resp.found == -1))
 	{
 	  /* The daemon does not cache this database.  */
-	  __nss_not_use_nscd_netgroup = 1;
+	  __nscd_defer_database (NSS_DBSIDX_netgroup);
 	  goto out_close;
 	}
 
diff --git a/nscd/nscd_proto.h b/nscd/nscd_proto.h
index d188699fbd..3b635620dc 100644
--- a/nscd/nscd_proto.h
+++ b/nscd/nscd_proto.h
@@ -28,13 +28,22 @@
 /* Type needed in the interfaces.  */
 struct nscd_ai_result;
 
+/* This is set to 1 by nscd client functions to request not using nscd
+   for a bit.  The main NSS code increments them until NSS_NSCD_RETRY
+   is reached, at which point nscd is attempted again.  If the counter
+   is 0 (the default), use of nscd is attempted.  If it is -1, nscd is
+   never used for this database.  */
+extern int __nscd_skip_counters[NSS_DBSIDX_max] attribute_hidden;
 
-/* Variables for communication between NSCD handler functions and NSS.  */
-extern int __nss_not_use_nscd_passwd attribute_hidden;
-extern int __nss_not_use_nscd_group attribute_hidden;
-extern int __nss_not_use_nscd_hosts attribute_hidden;
-extern int __nss_not_use_nscd_services attribute_hidden;
-extern int __nss_not_use_nscd_netgroup attribute_hidden;
+/* Update the internal per-database counters if necessary and return
+   true if nscd should be used for DATABASE for the next lookup.  */
+_Bool __nscd_use_database (int database) attribute_hidden;
+
+/* Stop using DATABASE until NSS_NSCD_RETRY lookups have been performed.  */
+void __nscd_defer_database (int database) attribute_hidden;
+
+/* Completely stop using DATABASE.  */
+void __nscd_disable_database (int database) attribute_hidden;
 
 extern int __nscd_getpwnam_r (const char *name, struct passwd *resultbuf,
 			      char *buffer, size_t buflen,
diff --git a/nscd/nscd_use_database.c b/nscd/nscd_use_database.c
new file mode 100644
index 0000000000..2d6e48e32d
--- /dev/null
+++ b/nscd/nscd_use_database.c
@@ -0,0 +1,57 @@
+/* Retry counter implementation for nscd.
+   Copyright (C) 2025 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 <nscd_proto.h>
+#include <atomic.h>
+
+int __nscd_skip_counters[NSS_DBSIDX_max];
+
+bool
+__nscd_use_database (int database)
+{
+  int counter;
+  while (true)
+    {
+      counter = atomic_load_relaxed (&__nscd_skip_counters[database]);
+      if (counter <= 0)
+        break;
+      else if (counter > 0)
+        {
+          int old_counter = counter;
+          ++counter;
+          if (counter > NSS_NSCD_RETRY)
+            counter = 0;
+          if (atomic_compare_exchange_weak_relaxed
+              (&__nscd_skip_counters[database], &old_counter, counter))
+            break;
+        }
+    }
+  return counter == 0;
+}
+
+void
+__nscd_defer_database (int database)
+{
+  atomic_store_relaxed (&__nscd_skip_counters[database], 1);
+}
+
+void
+__nscd_disable_database (int database)
+{
+  atomic_store_relaxed (&__nscd_skip_counters[database], -1);
+}
diff --git a/nscd/tst-nscd_use_database.c b/nscd/tst-nscd_use_database.c
new file mode 100644
index 0000000000..3e5d1169c5
--- /dev/null
+++ b/nscd/tst-nscd_use_database.c
@@ -0,0 +1,53 @@
+/* Test the __nscd_use_database function.
+   Copyright (C) 2025 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 <nscd_proto.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_hosts], 0);
+  TEST_VERIFY (__nscd_use_database (NSS_DBSIDX_hosts));
+  TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_hosts], 0);
+  TEST_VERIFY (__nscd_use_database (NSS_DBSIDX_hosts));
+
+  TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_group], 0);
+  __nscd_skip_counters[NSS_DBSIDX_group] = -1;
+  TEST_VERIFY (!__nscd_use_database (NSS_DBSIDX_group));
+  TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_group], -1);
+
+  TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_passwd], 0);
+  __nscd_defer_database (NSS_DBSIDX_passwd);
+  TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_passwd], 1);
+  TEST_VERIFY (!__nscd_use_database (NSS_DBSIDX_passwd));
+  for (int i = 2; i < NSS_NSCD_RETRY; ++i)
+    {
+      TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_passwd], i);
+      TEST_VERIFY (!__nscd_use_database (NSS_DBSIDX_passwd));
+    }
+  TEST_VERIFY (__nscd_use_database (NSS_DBSIDX_hosts));
+  TEST_COMPARE (__nscd_skip_counters[NSS_DBSIDX_hosts], 0);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
+
+/* Recompile due to use of internal symbol.  */
+#include "nscd_use_database.c"
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
index 9f7188ab41..37836fd040 100644
--- a/nss/getXXbyYY_r.c
+++ b/nss/getXXbyYY_r.c
@@ -78,9 +78,7 @@
 # define NSCD_NAME ADD_NSCD (REENTRANT_NAME)
 # define ADD_NSCD(name) ADD_NSCD1 (name)
 # define ADD_NSCD1(name) __nscd_##name
-# define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME)
-# define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name)
-# define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name
+# define NSS_DATABASE_INDEX CONCAT2 (NSS_DBSIDX_, DATABASE_NAME)
 # define CONCAT2(arg1, arg2) CONCAT2_2 (arg1, arg2)
 # define CONCAT2_2(arg1, arg2) arg1##arg2
 #endif
@@ -235,11 +233,7 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
 #endif
 
 #ifdef USE_NSCD
-  if (NOT_USENSCD_NAME > 0 && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
-    NOT_USENSCD_NAME = 0;
-
-  if (!NOT_USENSCD_NAME
-      && !__nss_database_custom[CONCAT2 (NSS_DBSIDX_, DATABASE_NAME)])
+  if (__nscd_use_database(NSS_DATABASE_INDEX))
     {
       nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result
 			       H_ERRNO_VAR);
diff --git a/nss/getaddrinfo.c b/nss/getaddrinfo.c
index 6726ace6fd..8605a980bb 100644
--- a/nss/getaddrinfo.c
+++ b/nss/getaddrinfo.c
@@ -81,7 +81,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <libc-lock.h>
 #include <not-cancel.h>
 #include <nscd/nscd-client.h>
-#include <nscd/nscd_proto.h>
+#ifdef USE_NSCD
+# include <nscd/nscd_proto.h>
+#endif
 #include <scratch_buffer.h>
 #include <inet/net-internal.h>
 
@@ -485,13 +487,9 @@ static int
 get_nscd_addresses (const char *name, const struct addrinfo *req,
 		    struct gaih_result *res)
 {
-  if (__nss_not_use_nscd_hosts > 0
-      && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
-    __nss_not_use_nscd_hosts = 0;
-
   res->at = NULL;
 
-  if (__nss_not_use_nscd_hosts || __nss_database_custom[NSS_DBSIDX_hosts])
+  if (!__nscd_use_database (NSS_DBSIDX_hosts))
     return 0;
 
   /* Try to use nscd.  */
@@ -503,7 +501,7 @@ get_nscd_addresses (const char *name, const struct addrinfo *req,
       /* The database contains a negative entry.  */
       if (err == 0)
 	return -EAI_NONAME;
-      if (__nss_not_use_nscd_hosts == 0)
+      if (atomic_load_relaxed (&__nscd_skip_counters[NSS_DBSIDX_hosts]) == 0)
 	{
 	  if (h_errno == NETDB_INTERNAL && errno == ENOMEM)
 	    return -EAI_MEMORY;
diff --git a/nss/getnetgrent_r.c b/nss/getnetgrent_r.c
index df16cfe150..11d3e8b562 100644
--- a/nss/getnetgrent_r.c
+++ b/nss/getnetgrent_r.c
@@ -150,12 +150,7 @@ static int
 nscd_setnetgrent (const char *group)
 {
 #ifdef USE_NSCD
-  if (__nss_not_use_nscd_netgroup > 0
-      && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
-    __nss_not_use_nscd_netgroup = 0;
-
-  if (!__nss_not_use_nscd_netgroup
-      && !__nss_database_custom[NSS_DBSIDX_netgroup])
+  if (__nscd_use_database (NSS_DBSIDX_netgroup))
     return __nscd_setnetgrent (group, &dataset);
 #endif
   return -1;
@@ -357,12 +352,7 @@ innetgr (const char *netgroup, const char *host, const char *user,
 	 const char *domain)
 {
 #ifdef USE_NSCD
-  if (__nss_not_use_nscd_netgroup > 0
-      && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
-    __nss_not_use_nscd_netgroup = 0;
-
-  if (!__nss_not_use_nscd_netgroup
-      && !__nss_database_custom[NSS_DBSIDX_netgroup])
+  if (__nscd_use_database (NSS_DBSIDX_netgroup))
     {
       int result = __nscd_innetgr (netgroup, host, user, domain);
       if (result >= 0)
diff --git a/nss/initgroups.c b/nss/initgroups.c
index 4a652ff782..e594622207 100644
--- a/nss/initgroups.c
+++ b/nss/initgroups.c
@@ -47,18 +47,11 @@ internal_getgrouplist (const char *user, gid_t group, long int *size,
 		       gid_t **groupsp, long int limit)
 {
 #ifdef USE_NSCD
-  if (__nss_not_use_nscd_group > 0
-      && ++__nss_not_use_nscd_group > NSS_NSCD_RETRY)
-    __nss_not_use_nscd_group = 0;
-  if (!__nss_not_use_nscd_group
-      && !__nss_database_custom[NSS_DBSIDX_group])
+  if (__nscd_use_database (NSS_DBSIDX_group))
     {
       int n = __nscd_getgrouplist (user, group, size, groupsp, limit);
       if (n >= 0)
 	return n;
-
-      /* nscd is not usable.  */
-      __nss_not_use_nscd_group = 1;
     }
 #endif
 
diff --git a/nss/nss_database.c b/nss/nss_database.c
index bed353c59b..66f91421b7 100644
--- a/nss/nss_database.c
+++ b/nss/nss_database.c
@@ -28,6 +28,9 @@
 #include <netdb.h>
 #include <stdio_ext.h>
 #include <string.h>
+#ifdef USE_NSCD
+# include <nscd/nscd_proto.h>
+#endif
 
 struct nss_database_state
 {
@@ -254,7 +257,7 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
   local->data.services[db] = result;
 
 #ifdef USE_NSCD
-  __nss_database_custom[db] = true;
+  __nscd_disable_database (db);
 #endif
 
   return 0;
diff --git a/nss/nss_module.c b/nss/nss_module.c
index ac94e4d3f0..7289d41f79 100644
--- a/nss/nss_module.c
+++ b/nss/nss_module.c
@@ -395,11 +395,8 @@ __nss_disable_nscd (void (*cb) (size_t, struct traced_file *))
   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;
+  for (int i = 0; i < NSS_DBSIDX_max; ++i)
+    __nscd_disable_database (i);
 }
 #endif
 
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index b23bb4c2c1..4d567b0e22 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -42,11 +42,6 @@
 #include <sysdep.h>
 #include <config.h>
 
-#ifdef USE_NSCD
-/* Flags whether custom rules for database is set.  */
-bool __nss_database_custom[NSS_DBSIDX_max];
-#endif
-
 /*__libc_lock_define_initialized (static, lock)*/
 
 /* -1 == not found
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
index 9799627aa2..6514a3d63d 100644
--- a/nss/nsswitch.h
+++ b/nss/nsswitch.h
@@ -73,8 +73,6 @@ enum
     NSS_DBSIDX_max
   };
 
-/* Flags whether custom rules for database is set.  */
-extern bool __nss_database_custom[NSS_DBSIDX_max] attribute_hidden;
 #endif
 
 /* Warning for NSS functions, which don't require dlopen if glibc

base-commit: 92186652d8653993ca51e97b895baf7edc745794



More information about the Libc-alpha mailing list