From patchwork Fri Mar 20 20:42:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 132109 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 26CFB4C318BC for ; Fri, 20 Mar 2026 20:45:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 26CFB4C318BC Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Os2WF/y7 X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 868AB4C9177A for ; Fri, 20 Mar 2026 20:42:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 868AB4C9177A Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 868AB4C9177A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774039330; cv=none; b=tYV/0msZ/muHLkCbx+2gB1ZbTxmyru+9fSB8aby6daQmkuydKFbwEkaYVjAlsBCvzHYGVWVs8yD96P/eiv2I6heL83FJRdLgWcQ5nkXGy3JpgzDph2/uvuV1db36RakpJXvWntO59PBGSocIbpP2yjxKeuS0JVEOkUPk4CKoE8Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774039330; c=relaxed/simple; bh=oVzyxNwb0xDcf7Erm7Yq6nyao16y+yEpnGqvyMnjyEk=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=fas8qMsOzkLUU2NDAvUka3K6qPESDT4uMMmBYDFpYazU7kLPW7KznWkPz1SMFI3Okv3azK3IRcpXBWRkJWpPc9PigmEco05kWBjlr/tFIutGxLJWuAfOwi9/H0f/KEzGHfVksbY4qrqrqcY2i17JB+t7+eZPMuP58SHs/LrqFRg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 868AB4C9177A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1774039330; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=OeVyl3q9Aeq9oDfRKba9XQ9A8uTY1enDimMqhu1hjRs=; b=Os2WF/y7LP3wNMULbguOjmundaRX9d4veZXoCD6o0CYQkfB4bzCMWn7cUh2yZ3E1Oi3tMA 4fPwGlnRO8VNqvtLS64oxJtm/a7LD/4fSOp7lkoPLH/bx5FE70xJT5HQUVl4CVs1Ab6N1Q vxs9iCf0M+ByjQryYSYRQ85vbg3Jj2Y= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-614-ZYR647gZPoe5t2RCd3GAIQ-1; Fri, 20 Mar 2026 16:42:08 -0400 X-MC-Unique: ZYR647gZPoe5t2RCd3GAIQ-1 X-Mimecast-MFC-AGG-ID: ZYR647gZPoe5t2RCd3GAIQ_1774039327 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CAE6B19560AA for ; Fri, 20 Mar 2026 20:42:07 +0000 (UTC) Received: from fweimer-oldenburg.csb.redhat.com (unknown [10.45.224.63]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A95C91955F21 for ; Fri, 20 Mar 2026 20:42:06 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH v2 08/23] nscd: Fix data races in client retry counters (bug 33654) In-Reply-To: Message-ID: <925c2367bd945a00033d4ddcd283e86d3b77c5b0.1774037705.git.fweimer@redhat.com> References: X-From-Line: 925c2367bd945a00033d4ddcd283e86d3b77c5b0 Mon Sep 17 00:00:00 2001 Date: Fri, 20 Mar 2026 21:42:04 +0100 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: rydzoiXkwhbHCsDw-5JxedGi03fZp-zOXqJtAM2cAEE_1774039327 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_HOSTKARMA_W, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_PASS, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Store the skip counters inside struct mapped_database. Introduce helper functions __nscd_use_database, __nscd_defer_database, __nscd_disable_database to access these counters. Teach the NSS code to translate to nscd database indices when calling these functions. Remove the special check from getaddrinfo (in get_nscd_addresses) that avoided fallback to an in-process operation for nscd protocol errors. Errors from service modules still produce a response from the nscd, so this check only avoided fallback if there were certain nscd communication errors. Checking the skip counters in this way for nscd usage was not reliable because another thread might have updated the skip counters. Reviewed-by: Carlos O'Donell --- nscd/nscd-client.h | 7 +++++++ nscd/nscd-dbtype.h | 3 +++ nscd/nscd_getai.c | 9 +++------ 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_helper.c | 41 +++++++++++++++++++++++++++++++++++++++++ nscd/nscd_initgroups.c | 5 +++-- nscd/nscd_netgroup.c | 10 ++++------ nscd/nscd_proto.h | 15 +++++++++------ nss/getXXbyYY_r.c | 11 +++-------- nss/getaddrinfo.c | 19 +++++-------------- nss/getnetgrent_r.c | 15 +++------------ nss/initgroups.c | 10 ++-------- nss/nss_database.c | 23 ++++++++++++++++++++++- nss/nss_module.c | 8 +++----- nss/nsswitch.c | 5 ----- nss/nsswitch.h | 20 ++++++++------------ 19 files changed, 126 insertions(+), 104 deletions(-) diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h index aff303b757..dd7421c5d1 100644 --- a/nscd/nscd-client.h +++ b/nscd/nscd-client.h @@ -354,6 +354,13 @@ struct mapped_database size_t mapsize; /* Zero means not in use. */ size_t datasize; + /* 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. */ + int skip_counter; + /* Use of the mapping must acquire a read lock. If the mapping is changed, acquire a write lock. */ __libc_rwlock_define (, lock); diff --git a/nscd/nscd-dbtype.h b/nscd/nscd-dbtype.h index 7d553d020a..262c96fd78 100644 --- a/nscd/nscd-dbtype.h +++ b/nscd/nscd-dbtype.h @@ -19,6 +19,9 @@ #ifndef NSCD_DBTYPE_H #define NSCD_DBTYPE_H +/* Note: If you add new database types here, you must add another call + to __nscd_disable_database in __nss_configure_lookup. */ + typedef enum { pwddb, diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c index a2e5da6b1c..65970b59ee 100644 --- a/nscd/nscd_getai.c +++ b/nscd/nscd_getai.c @@ -28,9 +28,6 @@ #include "nscd_proto.h" -/* Define in nscd_gethst_r.c. */ -extern int __nss_not_use_nscd_hosts; - /* Defined in nscd_gethst_r.c. */ extern int __nss_have_localdomain attribute_hidden; @@ -44,7 +41,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 (hstdb); return -1; } } @@ -93,7 +90,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 (hstdb); goto out; } } @@ -168,7 +165,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 (hstdb); goto out_close; } diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c index 746b11d792..f77650b25f 100644 --- a/nscd/nscd_getgr_r.c +++ b/nscd/nscd_getgr_r.c @@ -36,8 +36,6 @@ #include "nscd-dbtype.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); @@ -117,7 +115,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 (grpdb); goto out; } } @@ -128,7 +126,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 (grpdb); goto out_close; } diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c index 15d747fc33..9bb52614b7 100644 --- a/nscd/nscd_gethst_r.c +++ b/nscd/nscd_gethst_r.c @@ -27,8 +27,6 @@ #include "nscd-dbtype.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, @@ -81,7 +79,7 @@ __nscd_gethostbyaddr_r (const void *addr, socklen_t len, int type, uint32_t __nscd_get_nl_timestamp (void) { - if (__nss_not_use_nscd_hosts != 0) + if (!__nscd_use_database (hstdb)) return 0; int gc_cycle; @@ -112,7 +110,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 (hstdb); return -1; } } @@ -186,7 +184,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 (hstdb); goto out; } } @@ -197,7 +195,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 (hstdb); goto out_close; } diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c index 938eac9c70..8ce1009fe0 100644 --- a/nscd/nscd_getpw_r.c +++ b/nscd/nscd_getpw_r.c @@ -34,8 +34,6 @@ #include "nscd-dbtype.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); @@ -108,7 +106,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 (pwddb); goto out; } } @@ -119,7 +117,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 (pwddb); goto out_close; } diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c index 519078d8fe..8f0c010118 100644 --- a/nscd/nscd_getserv_r.c +++ b/nscd/nscd_getserv_r.c @@ -27,9 +27,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); @@ -162,7 +159,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 (servdb); goto out; } } @@ -173,7 +170,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 (servdb); goto out_close; } diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c index d3bfc208ad..2a60c3572e 100644 --- a/nscd/nscd_helper.c +++ b/nscd/nscd_helper.c @@ -40,6 +40,7 @@ #include "nscd-client.h" #include "nscd-dbtype.h" +#include "nscd_proto.h" /* Extra time we wait if the socket is still receiving data. This value is in milliseconds. Note that the other side is nscd on the @@ -413,6 +414,46 @@ __nscd_get_mapping (unsigned int db) __libc_rwlock_rdlock (mapped->lock); } +bool +__nscd_use_database (unsigned int db) +{ + assert (db < lastdb); + + int *pcounter = &__nscd_mapped_databases[db].skip_counter; + int counter; + while (true) + { + counter = atomic_load_relaxed (pcounter); + 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 + (pcounter, &old_counter, counter)) + break; + } + } + return counter == 0; +} + +void +__nscd_defer_database (unsigned int db) +{ + assert (db < lastdb); + atomic_store_relaxed (&__nscd_mapped_databases[db].skip_counter, 1); +} + +void +__nscd_disable_database (unsigned int db) +{ + assert (db < lastdb); + atomic_store_relaxed (&__nscd_mapped_databases[db].skip_counter, -1); +} + struct mapped_database * __nscd_get_map_ref (unsigned int db, int *gc_cyclep) { diff --git a/nscd/nscd_initgroups.c b/nscd/nscd_initgroups.c index f1e821b8d0..acc799cf55 100644 --- a/nscd/nscd_initgroups.c +++ b/nscd/nscd_initgroups.c @@ -16,6 +16,7 @@ . */ #include +#include #include #include #include @@ -79,7 +80,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; + __nscd_disable_database (grpdb); goto out; } } @@ -128,7 +129,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; + __nscd_disable_database (grpdb); goto out_close; } diff --git a/nscd/nscd_netgroup.c b/nscd/nscd_netgroup.c index 53649adc82..22c7cdcc9c 100644 --- a/nscd/nscd_netgroup.c +++ b/nscd/nscd_netgroup.c @@ -25,8 +25,6 @@ #include "nscd-dbtype.h" #include "nscd_proto.h" -int __nss_not_use_nscd_netgroup; - int __nscd_setnetgrent (const char *group, struct __netgrent *datap) { @@ -70,7 +68,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 (netgrdb); goto out; } } @@ -110,7 +108,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 (netgrdb); goto out_close; } @@ -207,7 +205,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 (netgrdb); goto out; } @@ -219,7 +217,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 (netgrdb); goto out_close; } diff --git a/nscd/nscd_proto.h b/nscd/nscd_proto.h index 917324aebd..6c4a318bc0 100644 --- a/nscd/nscd_proto.h +++ b/nscd/nscd_proto.h @@ -28,13 +28,16 @@ /* Type needed in the interfaces. */ struct nscd_ai_result; +/* Update the internal per-database counters if necessary and return + true if nscd should be used for DB for the next lookup. + DB is defined in . */ +_Bool __nscd_use_database (unsigned int db) 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; +/* Stop using DB until NSS_NSCD_RETRY lookups have been performed. */ +void __nscd_defer_database (unsigned int db) attribute_hidden; + +/* Completely stop using DB. */ +void __nscd_disable_database (unsigned int db) attribute_hidden; extern int __nscd_getpwnam_r (const char *name, struct passwd *resultbuf, char *buffer, size_t buflen, diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c index 21e82886b0..9527b6722d 100644 --- a/nss/getXXbyYY_r.c +++ b/nss/getXXbyYY_r.c @@ -23,6 +23,7 @@ #include "sysdep.h" #ifdef USE_NSCD # include +# include #endif #ifdef NEED__RES # include @@ -78,9 +79,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 +234,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 4f6ac3358a..233801052e 100644 --- a/nss/getaddrinfo.c +++ b/nss/getaddrinfo.c @@ -81,7 +81,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include +#ifdef USE_NSCD +# include +# include +#endif #include #include @@ -485,13 +488,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 (hstdb)) return 0; /* Try to use nscd. */ @@ -508,14 +507,6 @@ get_nscd_addresses (const char *name, const struct addrinfo *req, return -EAI_AGAIN; return -EAI_NONAME; } - if (__nss_not_use_nscd_hosts == 0) - { - if (h_errno == NETDB_INTERNAL && errno == ENOMEM) - return -EAI_MEMORY; - if (h_errno == TRY_AGAIN) - return -EAI_AGAIN; - return -EAI_SYSTEM; - } return 0; } diff --git a/nss/getnetgrent_r.c b/nss/getnetgrent_r.c index d391e2ac66..569087d3b0 100644 --- a/nss/getnetgrent_r.c +++ b/nss/getnetgrent_r.c @@ -27,6 +27,7 @@ #include "nsswitch.h" #include #include +#include /* Protect above variable against multiple uses at the same time. */ @@ -150,12 +151,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 (netgrdb)) return __nscd_setnetgrent (group, &dataset); #endif return -1; @@ -357,12 +353,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 (netgrdb)) { int result = __nscd_innetgr (netgroup, host, user, domain); if (result >= 0) diff --git a/nss/initgroups.c b/nss/initgroups.c index f4106226ec..95691542fb 100644 --- a/nss/initgroups.c +++ b/nss/initgroups.c @@ -29,6 +29,7 @@ #include #include "../nscd/nscd-client.h" +#include "../nscd/nscd-dbtype.h" #include "../nscd/nscd_proto.h" /* Type of the lookup function. */ @@ -47,18 +48,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 (grpdb)) { 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 076d5a63fe..5861454467 100644 --- a/nss/nss_database.c +++ b/nss/nss_database.c @@ -28,6 +28,10 @@ #include #include #include +#ifdef USE_NSCD +# include +# include +#endif struct nss_database_state { @@ -256,7 +260,24 @@ __nss_configure_lookup (const char *dbname, const char *service_line) local->data.services[db] = result; #ifdef USE_NSCD - __nss_database_custom[db] = true; + switch (db) + { + case nss_database_group: + __nscd_disable_database (grpdb); + break; + case nss_database_hosts: + __nscd_disable_database (hstdb); + break; + case nss_database_netgroup: + __nscd_disable_database (netgrdb); + break; + case nss_database_passwd: + __nscd_disable_database (pwddb); + break; + case nss_database_services: + __nscd_disable_database (servdb); + break; + } #endif return 0; diff --git a/nss/nss_module.c b/nss/nss_module.c index cb8fde38b4..fbbc6a266a 100644 --- a/nss/nss_module.c +++ b/nss/nss_module.c @@ -33,6 +33,7 @@ #include #include #include +#include /* 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 @@ -395,11 +396,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 < lastdb; ++i) + __nscd_disable_database (i); } #endif diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 97cedff826..ff69ede948 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -42,11 +42,6 @@ #include #include -#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 1b18794fee..b7cfb4f602 100644 --- a/nss/nsswitch.h +++ b/nss/nsswitch.h @@ -62,19 +62,15 @@ typedef struct /* To access the action based on the status value use this macro. */ #define nss_next_action(ni, status) nss_action_get (ni, status) - #ifdef USE_NSCD -/* Indices into DATABASES in nsswitch.c and __NSS_DATABASE_CUSTOM. */ -enum - { -# define DEFINE_DATABASE(arg) NSS_DBSIDX_##arg, -# include "databases.def" -# undef DEFINE_DATABASE - NSS_DBSIDX_max - }; - -/* Flags whether custom rules for database is set. */ -extern bool __nss_database_custom[NSS_DBSIDX_max] attribute_hidden; +/* Compile-time mapping of NSS databases to nscd dbtype values from + . This is used to update nscd usage counters + in nscd-enabled builds if getXbyY_r routines are called. */ +# define NSS_DBSIDX_group grpdb +# define NSS_DBSIDX_hosts hstdb +# define NSS_DBSIDX_netgroup netgrdb +# define NSS_DBSIDX_passwd pwddb +# define NSS_DBSIDX_services servdb #endif /* Warning for NSS functions, which don't require dlopen if glibc