From patchwork Thu Jul 2 00:32:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 39880 X-Patchwork-Delegate: carlos@redhat.com Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3CCBB386F812; Thu, 2 Jul 2020 00:32:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3CCBB386F812 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1593649965; bh=WQNqkMBarFqzqCmdIA4TOQr4+qJiAnGOPNZy6CQAv9c=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=y4EHfTAOKqV1YwjbZqDiZdFyAL3mpmboU+sF8WfPnTryUYSn2xnwCXh4oWlbqH3Fx CNKlKXbKfeiDYgkZm0vOXy97VOIorgJUimc2U0T98JLgfPXym927bd5UGIZIO7rZDy WhXoeR+Uorq+1OlY9zIRSoA9mLGdgx8xbURV/Pdc= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) by sourceware.org (Postfix) with ESMTP id 225043851C24 for ; Thu, 2 Jul 2020 00:32:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 225043851C24 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-178-izellVacOAmrsEYnStKbPQ-1; Wed, 01 Jul 2020 20:32:33 -0400 X-MC-Unique: izellVacOAmrsEYnStKbPQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E693F107ACCA for ; Thu, 2 Jul 2020 00:32:32 +0000 (UTC) Received: from greed.delorie.com (ovpn-113-9.phx2.redhat.com [10.3.113.9]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 82B1C73FF3 for ; Thu, 2 Jul 2020 00:32:32 +0000 (UTC) Received: from greed.delorie.com.redhat.com (localhost [127.0.0.1]) by greed.delorie.com (8.14.7/8.14.7) with ESMTP id 0620WVsQ009821 for ; Wed, 1 Jul 2020 20:32:31 -0400 Date: Wed, 01 Jul 2020 20:32:31 -0400 Message-Id: To: libc-alpha@sourceware.org Subject: v2 [PATCH 4/4] nsswitch: use new internal API X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.1 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: DJ Delorie via Libc-alpha From: DJ Delorie Reply-To: DJ Delorie Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Stitch new ABI and types throughout all NSS callers and providers. --- grp/compat-initgroups.c | 2 +- grp/initgroups.c | 41 +- inet/ether_hton.c | 21 +- inet/ether_ntoh.c | 21 +- inet/getnetgrent_r.c | 40 +- inet/netgroup.h | 2 +- malloc/set-freeres.c | 4 +- nscd/aicache.c | 17 +- nscd/gai.c | 2 +- nscd/initgrcache.c | 8 +- nscd/netgroupcache.c | 4 +- nscd/nscd_netgroup.c | 2 +- nss/XXX-lookup.c | 2 +- nss/compat-lookup.c | 8 +- nss/getXXbyYY_r.c | 10 +- nss/getXXent_r.c | 10 +- nss/getnssent_r.c | 22 +- nss/nss_action.c | 2 +- nss/nss_action_parse.c | 22 +- nss/nss_compat/compat-grp.c | 2 +- nss/nss_compat/compat-initgroups.c | 2 +- nss/nss_compat/compat-pwd.c | 2 +- nss/nss_compat/compat-spwd.c | 2 +- nss/nss_database.c | 40 +- nss/nss_module.c | 64 ++- nss/nsswitch.c | 817 ++--------------------------- nss/nsswitch.h | 69 +-- posix/tst-rfc3484-2.c | 2 +- posix/tst-rfc3484-3.c | 2 +- posix/tst-rfc3484.c | 2 +- sunrpc/netname.c | 21 +- sunrpc/publickey.c | 42 +- sysdeps/posix/getaddrinfo.c | 9 +- 33 files changed, 251 insertions(+), 1065 deletions(-) diff --git a/grp/compat-initgroups.c b/grp/compat-initgroups.c index 3dd50d2306..9df940767b 100644 --- a/grp/compat-initgroups.c +++ b/grp/compat-initgroups.c @@ -10,7 +10,7 @@ typedef enum nss_status (*get_function) (struct group *, char *, static enum nss_status -compat_call (service_user *nip, const char *user, gid_t group, long int *start, +compat_call (nss_action_list nip, const char *user, gid_t group, long int *start, long int *size, gid_t **groupsp, long int limit, int *errnop) { struct group grpbuf; diff --git a/grp/initgroups.c b/grp/initgroups.c index f4c4e986e9..88eb853496 100644 --- a/grp/initgroups.c +++ b/grp/initgroups.c @@ -69,7 +69,6 @@ internal_getgrouplist (const char *user, gid_t group, long int *size, #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); @@ -77,33 +76,28 @@ internal_getgrouplist (const char *user, gid_t group, long int *size, /* Start is one, because we have the first group as parameter. */ long int start = 1; - if (__nss_initgroups_database == NULL) - { - if (__nss_database_lookup2 ("initgroups", NULL, "", - &__nss_initgroups_database) < 0) - { - if (__nss_group_database == NULL) - no_more = __nss_database_lookup2 ("group", NULL, DEFAULT_CONFIG, - &__nss_group_database); + nss_action_list nip; - __nss_initgroups_database = __nss_group_database; - } - else - use_initgroups_entry = true; + if (__nss_database_get (nss_database_initgroups, &nip)) + { + use_initgroups_entry = true; + } + else if (__nss_database_get (nss_database_group, &nip)) + { + use_initgroups_entry = false; } else - /* __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; + { + nip = __nss_action_parse (DEFAULT_CONFIG); + use_initgroups_entry = false; + } - service_user *nip = __nss_initgroups_database; - while (! no_more) + while (nip && nip->module) { long int prev_start = start; - initgroups_dyn_function fct = __nss_lookup_function (nip, - "initgroups_dyn"); + initgroups_dyn_function fct = __nss_lookup_function (nip, "initgroups_dyn"); + if (fct == NULL) status = compat_call (nip, user, group, &start, size, groupsp, limit, &errno); @@ -140,10 +134,7 @@ internal_getgrouplist (const char *user, gid_t group, long int *size, && nss_next_action (nip, status) == NSS_ACTION_RETURN) break; - if (nip->next == NULL) - no_more = -1; - else - nip = nip->next; + nip ++; } return start; diff --git a/inet/ether_hton.c b/inet/ether_hton.c index ff6943fc35..cccae17f10 100644 --- a/inet/ether_hton.c +++ b/inet/ether_hton.c @@ -30,9 +30,7 @@ typedef int (*lookup_function) (const char *, struct etherent *, char *, int, int ether_hostton (const char *hostname, struct ether_addr *addr) { - static service_user *startp; - static lookup_function start_fct; - service_user *nip; + nss_action_list nip; union { lookup_function f; @@ -42,22 +40,7 @@ ether_hostton (const char *hostname, struct ether_addr *addr) enum nss_status status = NSS_STATUS_UNAVAIL; struct etherent etherent; - 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; - } + no_more = __nss_ethers_lookup2 (&nip, "gethostton_r", NULL, &fct.ptr); while (no_more == 0) { diff --git a/inet/ether_ntoh.c b/inet/ether_ntoh.c index e409773601..5ef654292c 100644 --- a/inet/ether_ntoh.c +++ b/inet/ether_ntoh.c @@ -31,9 +31,7 @@ typedef int (*lookup_function) (const struct ether_addr *, struct etherent *, int ether_ntohost (char *hostname, const struct ether_addr *addr) { - static service_user *startp; - static lookup_function start_fct; - service_user *nip; + nss_action_list nip; union { lookup_function f; @@ -43,22 +41,7 @@ ether_ntohost (char *hostname, const struct ether_addr *addr) enum nss_status status = NSS_STATUS_UNAVAIL; struct etherent etherent; - 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; - } + no_more = __nss_ethers_lookup2 (&nip, "getntohost_r", NULL, &fct.ptr); while (no_more == 0) { diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c index 78a66eee00..9c75af6f77 100644 --- a/inet/getnetgrent_r.c +++ b/inet/getnetgrent_r.c @@ -39,40 +39,12 @@ 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, service_user **nipp) +setup (void **fctp, nss_action_list *nipp) { - /* Remember the first service_entry, it's always the same. */ - static bool startp_initialized; - static service_user *startp; int no_more; - 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); - } + no_more = __nss_netgroup_lookup2 (nipp, "setnetgrent", NULL, fctp); + return no_more; } @@ -100,7 +72,7 @@ endnetgrent_hook (struct __netgrent *datap) { enum nss_status (*endfct) (struct __netgrent *); - if (datap->nip == NULL || datap->nip == (service_user *) -1l) + if (datap->nip == NULL || datap->nip == (nss_action_list) -1l) return; endfct = __nss_lookup_function (datap->nip, "endnetgrent"); @@ -133,7 +105,7 @@ __internal_setnetgrent_reuse (const char *group, struct __netgrent *datap, /* Ignore status, we force check in `__nss_next2'. */ status = DL_CALL_FCT (*fct.f, (group, datap)); - service_user *old_nip = datap->nip; + nss_action_list old_nip = datap->nip; no_more = __nss_next2 (&datap->nip, "setnetgrent", NULL, &fct.ptr, status, 0); @@ -275,7 +247,7 @@ __internal_getnetgrent_r (char **hostp, char **userp, char **domainp, /* 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 == (service_user *) -1l) + if (datap->nip == (nss_action_list) -1l) fct = nscd_getnetgrent; else #endif diff --git a/inet/netgroup.h b/inet/netgroup.h index 53081db78f..910094b9ca 100644 --- a/inet/netgroup.h +++ b/inet/netgroup.h @@ -64,7 +64,7 @@ struct __netgrent /* This handle for the NSS data base is shared between all set/get/endXXXent functions. */ - service_user *nip; + struct nss_action *nip; }; diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c index b328cca7c6..0769ad7a6f 100644 --- a/malloc/set-freeres.c +++ b/malloc/set-freeres.c @@ -20,7 +20,7 @@ #include #include -#include "../nss/nss_module.h" +#include "../nss/nsswitch.h" #include "../libio/libioP.h" DEFINE_HOOK (__libc_subfreeres, (void)); @@ -43,6 +43,8 @@ __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 (); diff --git a/nscd/aicache.c b/nscd/aicache.c index ee9c9b8843..ce3bb382ce 100644 --- a/nscd/aicache.c +++ b/nscd/aicache.c @@ -71,20 +71,15 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) key); } - static service_user *hosts_database; - service_user *nip; + nss_action_list nip; int no_more; int rc6 = 0; int rc4 = 0; int herrno = 0; - if (hosts_database == NULL) - no_more = __nss_database_lookup2 ("hosts", NULL, - "dns [!UNAVAIL=return] files", - &hosts_database); - else - no_more = 0; - nip = hosts_database; + no_more = __nss_database_lookup2 ("hosts", NULL, + "dns [!UNAVAIL=return] files", + &nip); /* Initialize configurations. */ struct resolv_context *ctx = __resolv_context_get (); @@ -442,10 +437,10 @@ next_nip: if (nss_next_action (nip, status[1]) == NSS_ACTION_RETURN) break; - if (nip->next == NULL) + if (nip[1].module == NULL) no_more = -1; else - nip = nip->next; + ++ nip; } /* No result found. Create a negative result record. */ diff --git a/nscd/gai.c b/nscd/gai.c index 2e19530102..aaaddd8fe5 100644 --- a/nscd/gai.c +++ b/nscd/gai.c @@ -43,4 +43,4 @@ #include /* Some variables normally defined in libc. */ -service_user *__nss_hosts_database attribute_hidden; +nss_action_list __nss_hosts_database attribute_hidden; diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c index a9f230bfb0..03cc52368e 100644 --- a/nscd/initgrcache.c +++ b/nscd/initgrcache.c @@ -83,8 +83,8 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in group cache!"), (char *) key); } - static service_user *group_database; - service_user *nip; + static nss_action_list group_database; + nss_action_list nip; int no_more; if (group_database == NULL) @@ -167,10 +167,10 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, && nss_next_action (nip, status) == NSS_ACTION_RETURN) break; - if (nip->next == NULL) + if (nip[1].module == NULL) no_more = -1; else - nip = nip->next; + ++ nip; } bool all_written; diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index 88c69d1e9c..67be24e837 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -124,7 +124,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in netgroup cache!"), key); } - static service_user *netgroup_database; + static nss_action_list netgroup_database; time_t timeout; struct dataset *dataset; bool cacheable = false; @@ -175,7 +175,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, void *ptr; } setfct; - service_user *nip = netgroup_database; + nss_action_list nip = netgroup_database; int no_more = __nss_lookup (&nip, "setnetgrent", NULL, &setfct.ptr); while (!no_more) { diff --git a/nscd/nscd_netgroup.c b/nscd/nscd_netgroup.c index 7b8dc4081a..0ed9c0cda6 100644 --- a/nscd/nscd_netgroup.c +++ b/nscd/nscd_netgroup.c @@ -116,7 +116,7 @@ __nscd_setnetgrent (const char *group, struct __netgrent *datap) datap->data_size = datalen; datap->cursor = respdata; datap->first = 1; - datap->nip = (service_user *) -1l; + datap->nip = (nss_action_list) -1l; datap->known_groups = NULL; datap->needed_groups = NULL; diff --git a/nss/XXX-lookup.c b/nss/XXX-lookup.c index e26c6d7f8b..d291968db3 100644 --- a/nss/XXX-lookup.c +++ b/nss/XXX-lookup.c @@ -53,7 +53,7 @@ #endif int -DB_LOOKUP_FCT (service_user **ni, const char *fct_name, const char *fct2_name, +DB_LOOKUP_FCT (nss_action_list *ni, const char *fct_name, const char *fct2_name, void **fctp) { if (DATABASE_NAME_SYMBOL == NULL diff --git a/nss/compat-lookup.c b/nss/compat-lookup.c index 9af34150bd..07fcc94f58 100644 --- a/nss/compat-lookup.c +++ b/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 (service_user **ni, const char *fct_name, void **fctp) +__nss_passwd_lookup (nss_action_list *ni, const char *fct_name, void **fctp) { __set_errno (ENOSYS); return -1; @@ -46,11 +46,11 @@ compat_symbol (libc, __nss_hosts_lookup, __nss_hosts_lookup, GLIBC_2_0); /* These functions were exported under a non-GLIBC_PRIVATE version, even though it is not usable externally due to the service_user - type dependency. */ + (now nss_action_list) type dependency. */ int attribute_compat_text_section -__nss_next (service_user **ni, const char *fct_name, void **fctp, int status, +__nss_next (nss_action_list *ni, const char *fct_name, void **fctp, int status, int all_values) { return -1; @@ -60,7 +60,7 @@ compat_symbol (libc, __nss_next, __nss_next, GLIBC_2_0); int attribute_compat_text_section __nss_database_lookup (const char *database, const char *alternate_name, - const char *defconfig, service_user **ni) + const char *defconfig, nss_action_list *ni) { *ni = NULL; return -1; diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c index e8c9ab1bb3..cbe78e6d66 100644 --- a/nss/getXXbyYY_r.c +++ b/nss/getXXbyYY_r.c @@ -179,7 +179,7 @@ typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *, EXTRA_PARAMS); /* The lookup function for the first entry of this service. */ -extern int DB_LOOKUP_FCT (service_user **nip, const char *name, +extern int DB_LOOKUP_FCT (nss_action_list *nip, const char *name, const char *name2, void **fctp); libc_hidden_proto (DB_LOOKUP_FCT) @@ -190,9 +190,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, EXTRA_PARAMS) { static bool startp_initialized; - static service_user *startp; + static nss_action_list startp; static lookup_function start_fct; - service_user *nip; + nss_action_list nip; int do_merge = 0; LOOKUP_TYPE mergegrp; char *mergebuf = NULL; @@ -270,7 +270,7 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, REENTRANT2_NAME_STRING, &fct.ptr); if (no_more) { - void *tmp_ptr = (service_user *) -1l; + void *tmp_ptr = (nss_action_list) -1l; #ifdef PTR_MANGLE PTR_MANGLE (tmp_ptr); #endif @@ -303,7 +303,7 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, PTR_DEMANGLE (fct.l); PTR_DEMANGLE (nip); #endif - no_more = nip == (service_user *) -1l; + no_more = nip == (nss_action_list) -1l; } while (no_more == 0) diff --git a/nss/getXXent_r.c b/nss/getXXent_r.c index 8b64fcd795..dfcbd01f66 100644 --- a/nss/getXXent_r.c +++ b/nss/getXXent_r.c @@ -95,11 +95,11 @@ /* This handle for the NSS data base is shared between all set/get/endXXXent functions. */ -static service_user *nip; +static nss_action_list nip; /* Remember the last service used since the last call to `endXXent'. */ -static service_user *last_nip; -/* Remember the first service_entry, it's always the same. */ -static service_user *startp; +static nss_action_list last_nip; +/* Remember the first service_entry across set/get/endent. */ +static nss_action_list 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 (service_user **nip, const char *name, +extern int DB_LOOKUP_FCT (nss_action_list *nip, const char *name, const char *name2, void **fctp); libc_hidden_proto (DB_LOOKUP_FCT) diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c index 8a366bc7ea..84e977c33b 100644 --- a/nss/getnssent_r.c +++ b/nss/getnssent_r.c @@ -25,20 +25,20 @@ services (left). */ static int setup (const char *func_name, db_lookup_function lookup_fct, - void **fctp, service_user **nip, service_user **startp, int all) + void **fctp, nss_action_list *nip, nss_action_list *startp, int all) { int no_more; - if (*startp == NULL) + if (*startp == NULL || all) { no_more = lookup_fct (nip, func_name, NULL, fctp); - *startp = no_more ? (service_user *) -1l : *nip; + *startp = no_more ? (nss_action_list) -1l : *nip; } - else if (*startp == (service_user *) -1l) + else if (*startp == (nss_action_list) -1l) /* No services at all. */ return 1; else { - if (all || !*nip) + if (!*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_function lookup_fct, void __nss_setent (const char *func_name, db_lookup_function lookup_fct, - service_user **nip, service_user **startp, - service_user **last_nip, int stayopen, int *stayopen_tmp, + nss_action_list *nip, nss_action_list *startp, + nss_action_list *last_nip, int stayopen, int *stayopen_tmp, int res) { union @@ -110,8 +110,8 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct, void __nss_endent (const char *func_name, db_lookup_function lookup_fct, - service_user **nip, service_user **startp, - service_user **last_nip, int res) + nss_action_list *nip, nss_action_list *startp, + nss_action_list *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, - service_user **nip, service_user **startp, - service_user **last_nip, int *stayopen_tmp, int res, + nss_action_list *nip, nss_action_list *startp, + nss_action_list *last_nip, int *stayopen_tmp, int res, void *resbuf, char *buffer, size_t buflen, void **result, int *h_errnop) { diff --git a/nss/nss_action.c b/nss/nss_action.c index aacaba2167..bb56f61bb4 100644 --- a/nss/nss_action.c +++ b/nss/nss_action.c @@ -16,7 +16,7 @@ License along with the GNU C Library; if not, see . */ -#include +#include #include #include diff --git a/nss/nss_action_parse.c b/nss/nss_action_parse.c index ada3acbb08..7a80582842 100644 --- a/nss/nss_action_parse.c +++ b/nss/nss_action_parse.c @@ -16,8 +16,7 @@ License along with the GNU C Library; if not, see . */ -#include "nss_action.h" -#include "nss_module.h" +#include #include #include @@ -169,18 +168,13 @@ nss_action_list action_list_init (&list); if (nss_action_parse (line, &list)) { - size_t size = action_list_size (&list); - nss_action_list result - = malloc (sizeof (*result) * (size + 1)); - if (result == NULL) - { - action_list_free (&list); - return NULL; - } - memcpy (result, action_list_begin (&list), sizeof (*result) * size); - /* Sentinel. */ - result[size].module = NULL; - return result; + 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)) { diff --git a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c index d4f750b95c..5593e075b4 100644 --- a/nss/nss_compat/compat-grp.c +++ b/nss/nss_compat/compat-grp.c @@ -29,7 +29,7 @@ NSS_DECLARE_MODULE_FUNCTIONS (compat) -static service_user *ni; +static nss_action_list ni; static enum nss_status (*setgrent_impl) (int stayopen); static enum nss_status (*getgrnam_r_impl) (const char *name, struct group * grp, char *buffer, diff --git a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c index 3671bef48b..0ce6141434 100644 --- a/nss/nss_compat/compat-initgroups.c +++ b/nss/nss_compat/compat-initgroups.c @@ -32,7 +32,7 @@ NSS_DECLARE_MODULE_FUNCTIONS (compat) -static service_user *ni; +static nss_action_list ni; static enum nss_status (*initgroups_dyn_impl) (const char *, gid_t, long int *, long int *, gid_t **, long int, int *); diff --git a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c index 394e39b811..8145fc2707 100644 --- a/nss/nss_compat/compat-pwd.c +++ b/nss/nss_compat/compat-pwd.c @@ -33,7 +33,7 @@ NSS_DECLARE_MODULE_FUNCTIONS (compat) -static service_user *ni; +static nss_action_list ni; static enum nss_status (*setpwent_impl) (int stayopen); static enum nss_status (*getpwnam_r_impl) (const char *name, struct passwd * pwd, char *buffer, diff --git a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c index ec5bf283cd..08dff30a59 100644 --- a/nss/nss_compat/compat-spwd.c +++ b/nss/nss_compat/compat-spwd.c @@ -33,7 +33,7 @@ NSS_DECLARE_MODULE_FUNCTIONS (compat) -static service_user *ni; +static nss_action_list 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, diff --git a/nss/nss_database.c b/nss/nss_database.c index 40162e0bc2..8508af51e3 100644 --- a/nss/nss_database.c +++ b/nss/nss_database.c @@ -226,6 +226,39 @@ process_line (struct nss_database_data *data, char *line) 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 @@ -326,8 +359,11 @@ nss_database_check_reload_and_get (struct nss_database_state *local, may have loaded the configuration first, so synchronize with the Release MO store there. */ if (atomic_load_acquire (&local->data.reload_disabled)) - /* No reload, so there is no error. */ - return true; + { + *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)) diff --git a/nss/nss_module.c b/nss/nss_module.c index 1c9eec0c01..59e46c5acb 100644 --- a/nss/nss_module.c +++ b/nss/nss_module.c @@ -16,7 +16,9 @@ License along with the GNU C Library; if not, see . */ -#include +#include +#include +#include #include #include @@ -357,6 +359,66 @@ __nss_module_get_function (struct nss_module *module, const char *name) 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 + void __libc_freeres_fn_section __nss_module_freeres (void) { diff --git a/nss/nsswitch.c b/nss/nsswitch.c index 319e22c3fc..9b73296c5f 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -32,6 +32,7 @@ #include #include #include +#include #if !defined DO_STATIC_NSS || defined SHARED # include @@ -42,44 +43,20 @@ #include #include -#ifdef LINK_OBSOLETE_NSL -# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -# define DEFAULT_DEFCONFIG "nis [NOTFOUND=return] files" -#else -# define DEFAULT_CONFIG "files" -# define DEFAULT_DEFCONFIG "files" -#endif - -/* 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) \ - service_user *__nss_##name##_database attribute_hidden; \ + nss_action_list __nss_##name##_database attribute_hidden; \ weak_extern (__nss_##name##_database) #include "databases.def" #undef DEFINE_DATABASE -/* 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" + #undef DEFINE_DATABASE +#define DEFINE_DATABASE(name) #name, +static const char * database_names[] = { +#include "databases.def" + NULL }; -#define ndatabases (sizeof (databases) / sizeof (databases[0])) #ifdef USE_NSCD /* Flags whether custom rules for database is set. */ @@ -87,103 +64,33 @@ bool __nss_database_custom[NSS_DBSIDX_max]; #endif -__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 - +/*__libc_lock_define_initialized (static, lock)*/ /* -1 == database not found 0 == database entry pointer stored */ int __nss_database_lookup2 (const char *database, const char *alternate_name, - const char *defconfig, service_user **ni) + const char *defconfig, nss_action_list *ni) { - /* Prevent multiple threads to change the service table. */ - __libc_lock_lock (lock); + int database_id; - /* 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; - } + for (database_id = 0; database_names[database_id]; database_id ++) + if (strcmp (database_names[database_id], database) == 0) + break; - /* Are we initialized yet? */ - if (service_table == NULL) - /* Read config file. */ - service_table = nss_parse_file (_PATH_NSSWITCH_CONF); + if (database_names[database_id] == NULL) + return -1; - /* Test whether configuration data is available. */ - if (service_table != NULL) + if (__nss_database_get (database_id, ni)) { - /* 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; + /* Success. */ + return 0; } - - /* 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) + else { - *ni = nss_parse_service_list (defconfig ?: DEFAULT_DEFCONFIG); - 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; - } - } + /* Failure. */ + return -1; } - - __libc_lock_unlock (lock); - - return *ni != NULL ? 0 : -1; } libc_hidden_def (__nss_database_lookup2) @@ -192,7 +99,7 @@ libc_hidden_def (__nss_database_lookup2) 0 == function found 1 == finished */ int -__nss_lookup (service_user **ni, const char *fct_name, const char *fct2_name, +__nss_lookup (nss_action_list *ni, const char *fct_name, const char *fct2_name, void **fctp) { *fctp = __nss_lookup_function (*ni, fct_name); @@ -201,16 +108,16 @@ __nss_lookup (service_user **ni, const char *fct_name, const char *fct2_name, while (*fctp == NULL && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE - && (*ni)->next != NULL) + && (*ni)[1].module != NULL) { - *ni = (*ni)->next; + ++ (*ni); *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)->next == NULL ? 1 : -1; + return *fctp != NULL ? 0 : (*ni)[1].module == NULL ? 1 : -1; } libc_hidden_def (__nss_lookup) @@ -219,7 +126,7 @@ libc_hidden_def (__nss_lookup) 0 == adjusted for next function 1 == finished */ int -__nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, +__nss_next2 (nss_action_list *ni, const char *fct_name, const char *fct2_name, void **fctp, int status, int all_values) { if (all_values) @@ -241,12 +148,12 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, return 1; } - if ((*ni)->next == NULL) + if ((*ni)[1].module == NULL) return -1; do { - *ni = (*ni)->next; + ++ (*ni); *fctp = __nss_lookup_function (*ni, fct_name); if (*fctp == NULL && fct2_name != NULL) @@ -254,675 +161,17 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, } while (*fctp == NULL && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE - && (*ni)->next != NULL); + && (*ni)[1].module != 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 (service_user *ni, const char *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) +__nss_lookup_function (nss_action_list ni, const char *fct_name) { - 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) + if (ni->module == NULL) return NULL; - - /* No threads use this stream. */ - __fsetlocking (fp, FSETLOCKING_BYCALLER); - - result = (name_database *) malloc (sizeof (name_database)); - if (result == NULL) - { - fclose (fp); - return NULL; - } - - result->entry = NULL; - result->library = NULL; - last = NULL; - line = NULL; - len = 0; - do - { - name_database_entry *this; - ssize_t n; - - n = __getline (&line, &len, fp); - if (n < 0) - break; - if (line[n - 1] == '\n') - line[n - 1] = '\0'; - - /* Because the file format does not know any form of quoting we - can search forward for the next '#' character and if found - make it terminating the line. */ - *__strchrnul (line, '#') = '\0'; - - /* If the line is blank it is ignored. */ - if (line[0] == '\0') - continue; - - /* Each line completely specifies the actions for a database. */ - this = nss_getline (line); - if (this != NULL) - { - if (last != NULL) - last->next = this; - else - result->entry = this; - - last = this; - } - } - while (!__feof_unlocked (fp)); - - /* Free the buffer. */ - free (line); - /* Close configuration file. */ - fclose (fp); - - return result; -} - - -/* Read the source names: - `( ( "[" "!"? ( "=" )+ "]" )? )*' - */ -static service_user * -nss_parse_service_list (const char *line) -{ - service_user *result = NULL, **nextp = &result; - - while (1) - { - service_user *new_service; - const char *name; - - while (isspace (line[0])) - ++line; - if (line[0] == '\0') - /* No source specified. */ - return result; - - /* Read identifier. */ - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') - ++line; - if (name == line) - return result; - - - new_service = (service_user *) malloc (sizeof (service_user) - + (line - name + 1)); - if (new_service == NULL) - return result; - - *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; - - /* Set default actions. */ - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; - new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; - new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; - new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; - new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; - new_service->library = NULL; - new_service->known = NULL; - new_service->next = NULL; - - while (isspace (line[0])) - ++line; - - if (line[0] == '[') - { - /* Read criterions. */ - do - ++line; - while (line[0] != '\0' && isspace (line[0])); - - do - { - int not; - enum nss_status status; - lookup_actions action; - - /* Grok ! before name to mean all statii but that one. */ - not = line[0] == '!'; - if (not) - ++line; - - /* Read status name. */ - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' - && line[0] != ']') - ++line; - - /* Compare with known statii. */ - if (line - name == 7) - { - if (__strncasecmp (name, "SUCCESS", 7) == 0) - status = NSS_STATUS_SUCCESS; - else if (__strncasecmp (name, "UNAVAIL", 7) == 0) - status = NSS_STATUS_UNAVAIL; - else - goto finish; - } - else if (line - name == 8) - { - if (__strncasecmp (name, "NOTFOUND", 8) == 0) - status = NSS_STATUS_NOTFOUND; - else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) - status = NSS_STATUS_TRYAGAIN; - else - goto finish; - } - else - goto finish; - - while (isspace (line[0])) - ++line; - if (line[0] != '=') - goto finish; - do - ++line; - while (isspace (line[0])); - - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' - && line[0] != ']') - ++line; - - if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) - action = NSS_ACTION_RETURN; - else if (line - name == 8 - && __strncasecmp (name, "CONTINUE", 8) == 0) - action = NSS_ACTION_CONTINUE; - else if (line - name == 5 - && __strncasecmp (name, "MERGE", 5) == 0) - action = NSS_ACTION_MERGE; - else - goto finish; - - if (not) - { - /* Save the current action setting for this status, - set them all to the given action, and reset this one. */ - const lookup_actions save = new_service->actions[2 + status]; - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; - new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; - new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; - new_service->actions[2 + NSS_STATUS_SUCCESS] = action; - new_service->actions[2 + status] = save; - } - else - new_service->actions[2 + status] = action; - - /* Skip white spaces. */ - while (isspace (line[0])) - ++line; - } - while (line[0] != ']'); - - /* Skip the ']'. */ - ++line; - } - - *nextp = new_service; - nextp = &new_service->next; - continue; - - finish: - free (new_service); - return result; - } -} - -static name_database_entry * -nss_getline (char *line) -{ - const char *name; - name_database_entry *result; - size_t len; - - /* Ignore leading white spaces. ATTENTION: this is different from - what is implemented in Solaris. The Solaris man page says a line - beginning with a white space character is ignored. We regard - this as just another misfeature in Solaris. */ - while (isspace (line[0])) - ++line; - - /* Recognize ` ":"'. */ - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') - ++line; - if (line[0] == '\0' || name == line) - /* Syntax error. */ - return NULL; - *line++ = '\0'; - - len = strlen (name) + 1; - - result = (name_database_entry *) malloc (sizeof (name_database_entry) + len); - if (result == NULL) - return NULL; - - /* Save the database name. */ - memcpy (result->name, name, len); - - /* Parse the list of services. */ - result->service = nss_parse_service_list (line); - - result->next = NULL; - return result; -} - - -#if !defined DO_STATIC_NSS || defined SHARED -static service_library * -nss_new_service (name_database *database, const char *name) -{ - service_library **currentp = &database->library; - - while (*currentp != NULL) - { - if (strcmp ((*currentp)->name, name) == 0) - return *currentp; - currentp = &(*currentp)->next; - } - - /* We have to add the new service. */ - *currentp = (service_library *) malloc (sizeof (service_library)); - if (*currentp == NULL) - return NULL; - - (*currentp)->name = name; - (*currentp)->lib_handle = NULL; - (*currentp)->next = NULL; - - return *currentp; -} -#endif - - -#if defined SHARED && defined USE_NSCD -/* Load all libraries for the service. */ -static void -nss_load_all_libraries (const char *service, const char *def) -{ - service_user *ni = NULL; - - if (__nss_database_lookup2 (service, NULL, def, &ni) == 0) - while (ni != NULL) - { - nss_load_library (ni); - ni = ni->next; - } -} - - -/* Called by nscd and nscd alone. */ -void -__nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) -{ -# ifdef PTR_MANGLE - PTR_MANGLE (cb); -# endif - nscd_init_cb = cb; - is_nscd = true; - - /* Find all the relevant modules so that the init functions are called. */ - nss_load_all_libraries ("passwd", DEFAULT_CONFIG); - nss_load_all_libraries ("group", DEFAULT_CONFIG); - 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); + return __nss_module_get_function (ni->module, fct_name); } +libc_hidden_def (__nss_lookup_function) diff --git a/nss/nsswitch.h b/nss/nsswitch.h index eaf81587d6..61b92a7115 100644 --- a/nss/nsswitch.h +++ b/nss/nsswitch.h @@ -36,6 +36,7 @@ typedef enum NSS_ACTION_MERGE } lookup_actions; +struct nss_action; typedef struct service_library { @@ -58,42 +59,8 @@ 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) ((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; +#define nss_next_action(ni, status) nss_action_get (ni, status) #ifdef USE_NSCD @@ -127,13 +94,13 @@ extern bool __nss_database_custom[NSS_DBSIDX_max] attribute_hidden; than one function can use the database. */ extern int __nss_database_lookup2 (const char *database, const char *alternative_name, - const char *defconfig, service_user **ni); + const char *defconfig, struct nss_action **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 (service_user **ni, const char *fct_name, +extern int __nss_lookup (struct nss_action **ni, const char *fct_name, const char *fct2_name, void **fctp); libc_hidden_proto (__nss_lookup) @@ -150,16 +117,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 (service_user **ni, const char *fct_name, +extern int __nss_next2 (struct nss_action **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 (service_user **ni, const char *fct_name, void **fctp, +extern int __nss_next (struct nss_action **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 (service_user *ni, const char *fct_name); +extern void *__nss_lookup_function (struct nss_action *ni, const char *fct_name); libc_hidden_proto (__nss_lookup_function) @@ -169,7 +136,7 @@ struct traced_file; extern void __nss_disable_nscd (void (*) (size_t, struct traced_file *)); -typedef int (*db_lookup_function) (service_user **, const char *, const char *, +typedef int (*db_lookup_function) (struct nss_action **, const char *, const char *, void **); typedef enum nss_status (*setent_function) (int); typedef enum nss_status (*endent_function) (void); @@ -180,20 +147,20 @@ typedef int (*getent_r_function) (void *, char *, size_t, extern void __nss_setent (const char *func_name, db_lookup_function lookup_fct, - service_user **nip, service_user **startp, - service_user **last_nip, int stayon, + struct nss_action **nip, struct nss_action **startp, + struct nss_action **last_nip, int stayon, int *stayon_tmp, int res) attribute_hidden; extern void __nss_endent (const char *func_name, db_lookup_function lookup_fct, - service_user **nip, service_user **startp, - service_user **last_nip, int res) + struct nss_action **nip, struct nss_action **startp, + struct nss_action **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, - service_user **nip, service_user **startp, - service_user **last_nip, int *stayon_tmp, + struct nss_action **nip, struct nss_action **startp, + struct nss_action **last_nip, int *stayon_tmp, int res, void *resbuf, char *buffer, size_t buflen, void **result, int *h_errnop) @@ -227,11 +194,15 @@ libc_hidden_proto (__nss_hostname_digits_dots) /* Prototypes for __nss_*_lookup2 functions. */ #define DEFINE_DATABASE(arg) \ - extern service_user *__nss_##arg##_database attribute_hidden; \ - int __nss_##arg##_lookup2 (service_user **, const char *, \ + extern struct nss_action *__nss_##arg##_database attribute_hidden; \ + int __nss_##arg##_lookup2 (struct nss_action **, const char *, \ const char *, void **); \ libc_hidden_proto (__nss_##arg##_lookup2) #include "databases.def" #undef DEFINE_DATABASE +#include +#include +#include + #endif /* nsswitch.h */ diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c index 8c64ac59ff..5f5ada9420 100644 --- a/posix/tst-rfc3484-2.c +++ b/posix/tst-rfc3484-2.c @@ -58,7 +58,7 @@ _res_hconf_init (void) #undef USE_NSCD #include "../sysdeps/posix/getaddrinfo.c" -service_user *__nss_hosts_database attribute_hidden; +nss_action_list __nss_hosts_database attribute_hidden; /* This is the beginning of the real test code. The above defines (among other things) the function rfc3484_sort. */ diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c index 1c61aaf844..d9ec5cc851 100644 --- a/posix/tst-rfc3484-3.c +++ b/posix/tst-rfc3484-3.c @@ -58,7 +58,7 @@ _res_hconf_init (void) #undef USE_NSCD #include "../sysdeps/posix/getaddrinfo.c" -service_user *__nss_hosts_database attribute_hidden; +nss_action_list __nss_hosts_database attribute_hidden; /* This is the beginning of the real test code. The above defines (among other things) the function rfc3484_sort. */ diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c index 8f45848e44..97d065b6bf 100644 --- a/posix/tst-rfc3484.c +++ b/posix/tst-rfc3484.c @@ -58,7 +58,7 @@ _res_hconf_init (void) #undef USE_NSCD #include "../sysdeps/posix/getaddrinfo.c" -service_user *__nss_hosts_database attribute_hidden; +nss_action_list __nss_hosts_database attribute_hidden; /* This is the beginning of the real test code. The above defines (among other things) the function rfc3484_sort. */ diff --git a/sunrpc/netname.c b/sunrpc/netname.c index 61d82ca31a..aa64362b4b 100644 --- a/sunrpc/netname.c +++ b/sunrpc/netname.c @@ -145,9 +145,7 @@ int netname2user (const char netname[MAXNETNAMELEN + 1], uid_t * uidp, gid_t * gidp, int *gidlenp, gid_t * gidlist) { - static service_user *startp; - static netname2user_function start_fct; - service_user *nip; + nss_action_list nip; union { netname2user_function f; @@ -156,22 +154,7 @@ netname2user (const char netname[MAXNETNAMELEN + 1], uid_t * uidp, gid_t * gidp, enum nss_status status = NSS_STATUS_UNAVAIL; int no_more; - 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; - } + no_more = __nss_publickey_lookup2 (&nip, "netname2user", NULL, &fct.ptr); while (!no_more) { diff --git a/sunrpc/publickey.c b/sunrpc/publickey.c index 2fa0252d5b..63866ef900 100644 --- a/sunrpc/publickey.c +++ b/sunrpc/publickey.c @@ -34,9 +34,7 @@ typedef int (*secret_function) (const char *, char *, const char *, int *); int getpublickey (const char *name, char *key) { - static service_user *startp; - static public_function start_fct; - service_user *nip; + nss_action_list nip; union { public_function f; @@ -45,22 +43,7 @@ getpublickey (const char *name, char *key) enum nss_status status = NSS_STATUS_UNAVAIL; int no_more; - 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; - } + no_more = __nss_publickey_lookup2 (&nip, "getpublickey", NULL, &fct.ptr); while (! no_more) { @@ -77,9 +60,7 @@ libc_hidden_nolink_sunrpc (getpublickey, GLIBC_2_0) int getsecretkey (const char *name, char *key, const char *passwd) { - static service_user *startp; - static secret_function start_fct; - service_user *nip; + nss_action_list nip; union { secret_function f; @@ -88,22 +69,7 @@ getsecretkey (const char *name, char *key, const char *passwd) enum nss_status status = NSS_STATUS_UNAVAIL; int no_more; - 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; - } + no_more = __nss_publickey_lookup2 (&nip, "getsecretkey", NULL, &fct.ptr); while (! no_more) { diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index ed04e564f9..84d3ce1957 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -307,7 +307,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, memory allocation failure. The returned string is allocated on the heap; the caller has to free it. */ static char * -getcanonname (service_user *nip, struct gaih_addrtuple *at, const char *name) +getcanonname (nss_action_list 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 struct gaih_service *service, struct gaih_addrtuple **pat = &at; int no_data = 0; int no_inet6_data = 0; - service_user *nip; + nss_action_list nip; enum nss_status inet6_status = NSS_STATUS_UNAVAIL; enum nss_status status = NSS_STATUS_UNAVAIL; int no_more; @@ -905,10 +905,9 @@ gaih_inet (const char *name, const struct gaih_service *service, if (nss_next_action (nip, status) == NSS_ACTION_RETURN) break; - if (nip->next == NULL) + nip ++; + if (nip->module == NULL) no_more = -1; - else - nip = nip->next; } __resolv_context_put (res_ctx);