Message ID | xn4klwdgw0.fsf@greed.delorie.com |
---|---|
State | New |
Headers | show |
Series | v4 [PATCH 4/6] nsswitch: use new internal API (core) | expand |
On 11/11/20 3:16 AM, DJ Delorie via Libc-alpha wrote: > > From 43edd0f9bf6621ed0c666c8b6da250ae9ca66ec5 Mon Sep 17 00:00:00 2001 > From: DJ Delorie <dj@redhat.com> > Date: Mon, 9 Nov 2020 22:06:57 -0500 > Subject: [PATCH 4/6] nsswitch: use new internal API (core) > > Core changes to switch the NSS internals to use the new API. Minor nits below. OK otherwise. > --- > malloc/set-freeres.c | 4 +- > nss/Makefile | 3 +- > nss/nss_action.c | 2 +- > nss/nss_action_parse.c | 22 +- > nss/nss_database.c | 40 +- > nss/nss_module.c | 64 +++- > nss/nsswitch.c | 809 ++--------------------------------------- > nss/nsswitch.h | 69 +--- > 8 files changed, 168 insertions(+), 845 deletions(-) > > 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 <set-hooks.h> > #include <libc-internal.h> > > -#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/nss/Makefile b/nss/Makefile > index ccd1a6ae4f..83323cb934 100644 > --- a/nss/Makefile > +++ b/nss/Makefile > @@ -66,7 +66,8 @@ tests-container = \ > tst-nss-test3 \ > tst-nss-files-hosts-long \ > tst-nss-db-endpwent \ > - tst-nss-db-endgrent > + tst-nss-db-endgrent \ > + tst-reload1 > > # Tests which need libdl > ifeq (yes,$(build-shared)) > diff --git a/nss/nss_action.c b/nss/nss_action.c > index b9c3b93fea..5008323859 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 > <https://www.gnu.org/licenses/>. */ > > -#include <nss_action.h> > +#include <nsswitch.h> > > #include <string.h> > #include <libc-lock.h> > diff --git a/nss/nss_action_parse.c b/nss/nss_action_parse.c > index 52acdbd9f2..c8a7319f19 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 > <https://www.gnu.org/licenses/>. */ > > -#include "nss_action.h" > -#include "nss_module.h" > +#include <nsswitch.h> > > #include <ctype.h> > #include <string.h> > @@ -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_database.c b/nss/nss_database.c > index 329bfb1262..e8c307d1f3 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 8de8db09c3..38d0ece020 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 > <https://www.gnu.org/licenses/>. */ > > -#include <nss_module.h> > +#include <nsswitch.h> > +#include <nscd/nscd.h> > +#include <nscd/nscd_proto.h> > > #include <array_length.h> > #include <assert.h> > @@ -287,6 +289,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 8d7b69d4bc..9b73296c5f 100644 > --- a/nss/nsswitch.c > +++ b/nss/nsswitch.c > @@ -32,6 +32,7 @@ > #include <netinet/ether.h> > #include <pwd.h> > #include <shadow.h> > +#include <unistd.h> > > #if !defined DO_STATIC_NSS || defined SHARED > # include <gnu/lib-names.h> > @@ -42,36 +43,20 @@ > #include <sysdep.h> > #include <config.h> > > -/* Prototypes for the local functions. */ > -static name_database *nss_parse_file (const char *fname); > -static name_database_entry *nss_getline (char *line); > -static service_user *nss_parse_service_list (const char *line); > -#if !defined DO_STATIC_NSS || defined SHARED > -static service_library *nss_new_service (name_database *database, > - const char *name); > -#endif > - > - > /* Declare external database variables. */ > #define DEFINE_DATABASE(name) \ > - 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. */ > @@ -79,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 ++) Unnecessary space before ++. This is a recurring issue in the patch. > + 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 ?: "files"); > - if (*ni != NULL) > - { > - /* Record the memory we've just allocated in defconfig_entries list, > - so we can free it later. */ > - name_database_entry *entry; > - > - /* Allocate ENTRY plus size of name (1 here). */ > - entry = (name_database_entry *) malloc (sizeof (*entry) + 1); > - > - if (entry != NULL) > - { > - entry->next = defconfig_entries; > - entry->service = *ni; > - entry->name[0] = '\0'; > - defconfig_entries = entry; > - } > - } > + /* Failure. */ > + return -1; > } > - > - __libc_lock_unlock (lock); > - > - return *ni != NULL ? 0 : -1; > } > libc_hidden_def (__nss_database_lookup2) > > @@ -184,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); > @@ -193,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) > > @@ -211,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) > @@ -233,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) > @@ -246,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: > - `( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*' > - */ > -static service_user * > -nss_parse_service_list (const char *line) > -{ > - service_user *result = NULL, **nextp = &result; > - > - while (1) > - { > - service_user *new_service; > - const char *name; > - > - while (isspace (line[0])) > - ++line; > - if (line[0] == '\0') > - /* No source specified. */ > - return result; > - > - /* Read <source> identifier. */ > - name = line; > - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') > - ++line; > - if (name == line) > - return result; > - > - > - new_service = (service_user *) malloc (sizeof (service_user) > - + (line - name + 1)); > - if (new_service == NULL) > - return result; > - > - *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; > - > - /* Set default actions. */ > - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; > - new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; > - new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; > - new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; > - new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; > - new_service->library = NULL; > - new_service->known = NULL; > - new_service->next = NULL; > - > - while (isspace (line[0])) > - ++line; > - > - if (line[0] == '[') > - { > - /* Read criterions. */ > - do > - ++line; > - while (line[0] != '\0' && isspace (line[0])); > - > - do > - { > - int not; > - enum nss_status status; > - lookup_actions action; > - > - /* Grok ! before name to mean all statii but that one. */ > - not = line[0] == '!'; > - if (not) > - ++line; > - > - /* Read status name. */ > - name = line; > - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' > - && line[0] != ']') > - ++line; > - > - /* Compare with known statii. */ > - if (line - name == 7) > - { > - if (__strncasecmp (name, "SUCCESS", 7) == 0) > - status = NSS_STATUS_SUCCESS; > - else if (__strncasecmp (name, "UNAVAIL", 7) == 0) > - status = NSS_STATUS_UNAVAIL; > - else > - goto finish; > - } > - else if (line - name == 8) > - { > - if (__strncasecmp (name, "NOTFOUND", 8) == 0) > - status = NSS_STATUS_NOTFOUND; > - else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) > - status = NSS_STATUS_TRYAGAIN; > - else > - goto finish; > - } > - else > - goto finish; > - > - while (isspace (line[0])) > - ++line; > - if (line[0] != '=') > - goto finish; > - do > - ++line; > - while (isspace (line[0])); > - > - name = line; > - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' > - && line[0] != ']') > - ++line; > - > - if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) > - action = NSS_ACTION_RETURN; > - else if (line - name == 8 > - && __strncasecmp (name, "CONTINUE", 8) == 0) > - action = NSS_ACTION_CONTINUE; > - else if (line - name == 5 > - && __strncasecmp (name, "MERGE", 5) == 0) > - action = NSS_ACTION_MERGE; > - else > - goto finish; > - > - if (not) > - { > - /* Save the current action setting for this status, > - set them all to the given action, and reset this one. */ > - const lookup_actions save = new_service->actions[2 + status]; > - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; > - new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; > - new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; > - new_service->actions[2 + NSS_STATUS_SUCCESS] = action; > - new_service->actions[2 + status] = save; > - } > - else > - new_service->actions[2 + status] = action; > - > - /* Skip white spaces. */ > - while (isspace (line[0])) > - ++line; > - } > - while (line[0] != ']'); > - > - /* Skip the ']'. */ > - ++line; > - } > - > - *nextp = new_service; > - nextp = &new_service->next; > - continue; > - > - finish: > - free (new_service); > - return result; > - } > -} > - > -static name_database_entry * > -nss_getline (char *line) > -{ > - const char *name; > - name_database_entry *result; > - size_t len; > - > - /* Ignore leading white spaces. ATTENTION: this is different from > - what is implemented in Solaris. The Solaris man page says a line > - beginning with a white space character is ignored. We regard > - this as just another misfeature in Solaris. */ > - while (isspace (line[0])) > - ++line; > - > - /* Recognize `<database> ":"'. */ > - name = line; > - while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') > - ++line; > - if (line[0] == '\0' || name == line) > - /* Syntax error. */ > - return NULL; > - *line++ = '\0'; > - > - len = strlen (name) + 1; > - > - result = (name_database_entry *) malloc (sizeof (name_database_entry) + len); > - if (result == NULL) > - return NULL; > - > - /* Save the database name. */ > - memcpy (result->name, name, len); > - > - /* Parse the list of services. */ > - result->service = nss_parse_service_list (line); > - > - result->next = NULL; > - return result; > -} > - > - > -#if !defined DO_STATIC_NSS || defined SHARED > -static service_library * > -nss_new_service (name_database *database, const char *name) > -{ > - service_library **currentp = &database->library; > - > - while (*currentp != NULL) > - { > - if (strcmp ((*currentp)->name, name) == 0) > - return *currentp; > - currentp = &(*currentp)->next; > - } > - > - /* We have to add the new service. */ > - *currentp = (service_library *) malloc (sizeof (service_library)); > - if (*currentp == NULL) > - return NULL; > - > - (*currentp)->name = name; > - (*currentp)->lib_handle = NULL; > - (*currentp)->next = NULL; > - > - return *currentp; > -} > -#endif > - > - > -#if defined SHARED && defined USE_NSCD > -/* Load all libraries for the service. */ > -static void > -nss_load_all_libraries (const char *service, const char *def) > -{ > - service_user *ni = NULL; > - > - if (__nss_database_lookup2 (service, NULL, def, &ni) == 0) > - while (ni != NULL) > - { > - nss_load_library (ni); > - ni = ni->next; > - } > -} > - > - > -/* Called by nscd and nscd alone. */ > -void > -__nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) > -{ > -# ifdef PTR_MANGLE > - PTR_MANGLE (cb); > -# endif > - nscd_init_cb = cb; > - is_nscd = true; > - > - /* Find all the relevant modules so that the init functions are called. */ > - nss_load_all_libraries ("passwd", "files"); > - nss_load_all_libraries ("group", "files"); > - nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files"); > - nss_load_all_libraries ("services", NULL); > - > - /* Disable all uses of NSCD. */ > - __nss_not_use_nscd_passwd = -1; > - __nss_not_use_nscd_group = -1; > - __nss_not_use_nscd_hosts = -1; > - __nss_not_use_nscd_services = -1; > - __nss_not_use_nscd_netgroup = -1; > -} > -#endif > - > -static void > -free_database_entries (name_database_entry *entry) > -{ > - while (entry != NULL) > - { > - name_database_entry *olde = entry; > - service_user *service = entry->service; > - > - while (service != NULL) > - { > - service_user *olds = service; > - > - if (service->known != NULL) > - __tdestroy (service->known, free); > - > - service = service->next; > - free (olds); > - } > - > - entry = entry->next; > - free (olde); > - } > -} > - > -/* Free all resources if necessary. */ > -libc_freeres_fn (free_defconfig) > -{ > - name_database_entry *entry = defconfig_entries; > - > - if (entry == NULL) > - /* defconfig was not used. */ > - return; > - > - /* Don't disturb ongoing other threads (if there are any). */ > - defconfig_entries = NULL; > - > - free_database_entries (entry); > -} > - > -libc_freeres_fn (free_mem) > -{ > - name_database *top = service_table; > - service_library *library; > - > - if (top == NULL) > - /* Maybe we have not read the nsswitch.conf file. */ > - return; > - > - /* Don't disturb ongoing other threads (if there are any). */ > - service_table = NULL; > - > - free_database_entries (top->entry); > - > - library = top->library; > - while (library != NULL) > - { > - service_library *oldl = library; > - > - if (library->lib_handle && library->lib_handle != (void *) -1l) > - __libc_dlclose (library->lib_handle); > - > - library = library->next; > - free (oldl); > - } > - > - free (top); > + 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 <nss/nss_module.h> > +#include <nss/nss_action.h> > +#include <nss/nss_database.h> > + > #endif /* nsswitch.h */ >
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 <set-hooks.h> #include <libc-internal.h> -#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/nss/Makefile b/nss/Makefile index ccd1a6ae4f..83323cb934 100644 --- a/nss/Makefile +++ b/nss/Makefile @@ -66,7 +66,8 @@ tests-container = \ tst-nss-test3 \ tst-nss-files-hosts-long \ tst-nss-db-endpwent \ - tst-nss-db-endgrent + tst-nss-db-endgrent \ + tst-reload1 # Tests which need libdl ifeq (yes,$(build-shared)) diff --git a/nss/nss_action.c b/nss/nss_action.c index b9c3b93fea..5008323859 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 <https://www.gnu.org/licenses/>. */ -#include <nss_action.h> +#include <nsswitch.h> #include <string.h> #include <libc-lock.h> diff --git a/nss/nss_action_parse.c b/nss/nss_action_parse.c index 52acdbd9f2..c8a7319f19 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 <https://www.gnu.org/licenses/>. */ -#include "nss_action.h" -#include "nss_module.h" +#include <nsswitch.h> #include <ctype.h> #include <string.h> @@ -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_database.c b/nss/nss_database.c index 329bfb1262..e8c307d1f3 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 8de8db09c3..38d0ece020 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 <https://www.gnu.org/licenses/>. */ -#include <nss_module.h> +#include <nsswitch.h> +#include <nscd/nscd.h> +#include <nscd/nscd_proto.h> #include <array_length.h> #include <assert.h> @@ -287,6 +289,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 8d7b69d4bc..9b73296c5f 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -32,6 +32,7 @@ #include <netinet/ether.h> #include <pwd.h> #include <shadow.h> +#include <unistd.h> #if !defined DO_STATIC_NSS || defined SHARED # include <gnu/lib-names.h> @@ -42,36 +43,20 @@ #include <sysdep.h> #include <config.h> -/* Prototypes for the local functions. */ -static name_database *nss_parse_file (const char *fname); -static name_database_entry *nss_getline (char *line); -static service_user *nss_parse_service_list (const char *line); -#if !defined DO_STATIC_NSS || defined SHARED -static service_library *nss_new_service (name_database *database, - const char *name); -#endif - - /* Declare external database variables. */ #define DEFINE_DATABASE(name) \ - 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. */ @@ -79,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 ?: "files"); - if (*ni != NULL) - { - /* Record the memory we've just allocated in defconfig_entries list, - so we can free it later. */ - name_database_entry *entry; - - /* Allocate ENTRY plus size of name (1 here). */ - entry = (name_database_entry *) malloc (sizeof (*entry) + 1); - - if (entry != NULL) - { - entry->next = defconfig_entries; - entry->service = *ni; - entry->name[0] = '\0'; - defconfig_entries = entry; - } - } + /* Failure. */ + return -1; } - - __libc_lock_unlock (lock); - - return *ni != NULL ? 0 : -1; } libc_hidden_def (__nss_database_lookup2) @@ -184,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); @@ -193,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) @@ -211,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) @@ -233,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) @@ -246,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: - `( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*' - */ -static service_user * -nss_parse_service_list (const char *line) -{ - service_user *result = NULL, **nextp = &result; - - while (1) - { - service_user *new_service; - const char *name; - - while (isspace (line[0])) - ++line; - if (line[0] == '\0') - /* No source specified. */ - return result; - - /* Read <source> identifier. */ - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') - ++line; - if (name == line) - return result; - - - new_service = (service_user *) malloc (sizeof (service_user) - + (line - name + 1)); - if (new_service == NULL) - return result; - - *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; - - /* Set default actions. */ - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; - new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; - new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; - new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; - new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; - new_service->library = NULL; - new_service->known = NULL; - new_service->next = NULL; - - while (isspace (line[0])) - ++line; - - if (line[0] == '[') - { - /* Read criterions. */ - do - ++line; - while (line[0] != '\0' && isspace (line[0])); - - do - { - int not; - enum nss_status status; - lookup_actions action; - - /* Grok ! before name to mean all statii but that one. */ - not = line[0] == '!'; - if (not) - ++line; - - /* Read status name. */ - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' - && line[0] != ']') - ++line; - - /* Compare with known statii. */ - if (line - name == 7) - { - if (__strncasecmp (name, "SUCCESS", 7) == 0) - status = NSS_STATUS_SUCCESS; - else if (__strncasecmp (name, "UNAVAIL", 7) == 0) - status = NSS_STATUS_UNAVAIL; - else - goto finish; - } - else if (line - name == 8) - { - if (__strncasecmp (name, "NOTFOUND", 8) == 0) - status = NSS_STATUS_NOTFOUND; - else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) - status = NSS_STATUS_TRYAGAIN; - else - goto finish; - } - else - goto finish; - - while (isspace (line[0])) - ++line; - if (line[0] != '=') - goto finish; - do - ++line; - while (isspace (line[0])); - - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' - && line[0] != ']') - ++line; - - if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) - action = NSS_ACTION_RETURN; - else if (line - name == 8 - && __strncasecmp (name, "CONTINUE", 8) == 0) - action = NSS_ACTION_CONTINUE; - else if (line - name == 5 - && __strncasecmp (name, "MERGE", 5) == 0) - action = NSS_ACTION_MERGE; - else - goto finish; - - if (not) - { - /* Save the current action setting for this status, - set them all to the given action, and reset this one. */ - const lookup_actions save = new_service->actions[2 + status]; - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; - new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; - new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; - new_service->actions[2 + NSS_STATUS_SUCCESS] = action; - new_service->actions[2 + status] = save; - } - else - new_service->actions[2 + status] = action; - - /* Skip white spaces. */ - while (isspace (line[0])) - ++line; - } - while (line[0] != ']'); - - /* Skip the ']'. */ - ++line; - } - - *nextp = new_service; - nextp = &new_service->next; - continue; - - finish: - free (new_service); - return result; - } -} - -static name_database_entry * -nss_getline (char *line) -{ - const char *name; - name_database_entry *result; - size_t len; - - /* Ignore leading white spaces. ATTENTION: this is different from - what is implemented in Solaris. The Solaris man page says a line - beginning with a white space character is ignored. We regard - this as just another misfeature in Solaris. */ - while (isspace (line[0])) - ++line; - - /* Recognize `<database> ":"'. */ - name = line; - while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':') - ++line; - if (line[0] == '\0' || name == line) - /* Syntax error. */ - return NULL; - *line++ = '\0'; - - len = strlen (name) + 1; - - result = (name_database_entry *) malloc (sizeof (name_database_entry) + len); - if (result == NULL) - return NULL; - - /* Save the database name. */ - memcpy (result->name, name, len); - - /* Parse the list of services. */ - result->service = nss_parse_service_list (line); - - result->next = NULL; - return result; -} - - -#if !defined DO_STATIC_NSS || defined SHARED -static service_library * -nss_new_service (name_database *database, const char *name) -{ - service_library **currentp = &database->library; - - while (*currentp != NULL) - { - if (strcmp ((*currentp)->name, name) == 0) - return *currentp; - currentp = &(*currentp)->next; - } - - /* We have to add the new service. */ - *currentp = (service_library *) malloc (sizeof (service_library)); - if (*currentp == NULL) - return NULL; - - (*currentp)->name = name; - (*currentp)->lib_handle = NULL; - (*currentp)->next = NULL; - - return *currentp; -} -#endif - - -#if defined SHARED && defined USE_NSCD -/* Load all libraries for the service. */ -static void -nss_load_all_libraries (const char *service, const char *def) -{ - service_user *ni = NULL; - - if (__nss_database_lookup2 (service, NULL, def, &ni) == 0) - while (ni != NULL) - { - nss_load_library (ni); - ni = ni->next; - } -} - - -/* Called by nscd and nscd alone. */ -void -__nss_disable_nscd (void (*cb) (size_t, struct traced_file *)) -{ -# ifdef PTR_MANGLE - PTR_MANGLE (cb); -# endif - nscd_init_cb = cb; - is_nscd = true; - - /* Find all the relevant modules so that the init functions are called. */ - nss_load_all_libraries ("passwd", "files"); - nss_load_all_libraries ("group", "files"); - nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files"); - nss_load_all_libraries ("services", NULL); - - /* Disable all uses of NSCD. */ - __nss_not_use_nscd_passwd = -1; - __nss_not_use_nscd_group = -1; - __nss_not_use_nscd_hosts = -1; - __nss_not_use_nscd_services = -1; - __nss_not_use_nscd_netgroup = -1; -} -#endif - -static void -free_database_entries (name_database_entry *entry) -{ - while (entry != NULL) - { - name_database_entry *olde = entry; - service_user *service = entry->service; - - while (service != NULL) - { - service_user *olds = service; - - if (service->known != NULL) - __tdestroy (service->known, free); - - service = service->next; - free (olds); - } - - entry = entry->next; - free (olde); - } -} - -/* Free all resources if necessary. */ -libc_freeres_fn (free_defconfig) -{ - name_database_entry *entry = defconfig_entries; - - if (entry == NULL) - /* defconfig was not used. */ - return; - - /* Don't disturb ongoing other threads (if there are any). */ - defconfig_entries = NULL; - - free_database_entries (entry); -} - -libc_freeres_fn (free_mem) -{ - name_database *top = service_table; - service_library *library; - - if (top == NULL) - /* Maybe we have not read the nsswitch.conf file. */ - return; - - /* Don't disturb ongoing other threads (if there are any). */ - service_table = NULL; - - free_database_entries (top->entry); - - library = top->library; - while (library != NULL) - { - service_library *oldl = library; - - if (library->lib_handle && library->lib_handle != (void *) -1l) - __libc_dlclose (library->lib_handle); - - library = library->next; - free (oldl); - } - - free (top); + 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 <nss/nss_module.h> +#include <nss/nss_action.h> +#include <nss/nss_database.h> + #endif /* nsswitch.h */
From 43edd0f9bf6621ed0c666c8b6da250ae9ca66ec5 Mon Sep 17 00:00:00 2001 From: DJ Delorie <dj@redhat.com> Date: Mon, 9 Nov 2020 22:06:57 -0500 Subject: [PATCH 4/6] nsswitch: use new internal API (core) Core changes to switch the NSS internals to use the new API. --- malloc/set-freeres.c | 4 +- nss/Makefile | 3 +- nss/nss_action.c | 2 +- nss/nss_action_parse.c | 22 +- nss/nss_database.c | 40 +- nss/nss_module.c | 64 +++- nss/nsswitch.c | 809 ++--------------------------------------- nss/nsswitch.h | 69 +--- 8 files changed, 168 insertions(+), 845 deletions(-)