1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00

nss: Directly load nss_dns, without going through dlsym/dlopen

This partially fixes static-only NSS support (bug 27959): The dns
module no longer needs dlopen.  Support for disabling dlopen altogher
remains to be added.

This commit introduces module_load_builtin into nss/nss_module.c, which
handles the common parts of loading the built-in nss_files and nss_dns
modules.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
Florian Weimer
2021-07-19 07:55:27 +02:00
parent e1fcf21474
commit ee5ed99922
6 changed files with 105 additions and 33 deletions

View File

@ -24,13 +24,16 @@
NSS_DECLARE_MODULE_FUNCTIONS (dns) NSS_DECLARE_MODULE_FUNCTIONS (dns)
libc_hidden_proto (_nss_dns_getcanonname_r) libc_hidden_proto (_nss_dns_getcanonname_r)
libc_hidden_proto (_nss_dns_gethostbyname3_r)
libc_hidden_proto (_nss_dns_gethostbyname2_r)
libc_hidden_proto (_nss_dns_gethostbyname_r)
libc_hidden_proto (_nss_dns_gethostbyname4_r)
libc_hidden_proto (_nss_dns_gethostbyaddr2_r) libc_hidden_proto (_nss_dns_gethostbyaddr2_r)
libc_hidden_proto (_nss_dns_gethostbyaddr_r) libc_hidden_proto (_nss_dns_gethostbyaddr_r)
libc_hidden_proto (_nss_dns_getnetbyname_r) libc_hidden_proto (_nss_dns_gethostbyname2_r)
libc_hidden_proto (_nss_dns_gethostbyname3_r)
libc_hidden_proto (_nss_dns_gethostbyname4_r)
libc_hidden_proto (_nss_dns_gethostbyname_r)
libc_hidden_proto (_nss_dns_getnetbyaddr_r) libc_hidden_proto (_nss_dns_getnetbyaddr_r)
libc_hidden_proto (_nss_dns_getnetbyname_r)
void __nss_dns_functions (nss_module_functions_untyped pointers)
attribute_hidden;
#endif #endif

View File

@ -34,10 +34,4 @@ __nss_files_functions (nss_module_functions_untyped pointers)
#undef DEFINE_NSS_FUNCTION #undef DEFINE_NSS_FUNCTION
#define DEFINE_NSS_FUNCTION(x) *fptr++ = _nss_files_##x; #define DEFINE_NSS_FUNCTION(x) *fptr++ = _nss_files_##x;
#include "function.def" #include "function.def"
#ifdef PTR_MANGLE
void **end = fptr;
for (fptr = pointers; fptr != end; ++fptr)
PTR_MANGLE (*fptr);
#endif
} }

View File

@ -26,11 +26,13 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <gnu/lib-names.h> #include <gnu/lib-names.h>
#include <libc-lock.h> #include <libc-lock.h>
#include <nss_dns.h>
#include <nss_files.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <nss_files.h> #include <sysdep.h>
/* Suffix after .so of NSS service modules. This is a bit of magic, /* Suffix after .so of NSS service modules. This is a bit of magic,
but we assume LIBNSS_FILES_SO looks like "libnss_files.so.2" and we but we assume LIBNSS_FILES_SO looks like "libnss_files.so.2" and we
@ -111,6 +113,39 @@ static const function_name nss_function_name_array[] =
#include "function.def" #include "function.def"
}; };
/* Loads a built-in module, binding the symbols using the supplied
callback function. Always returns true. */
static bool
module_load_builtin (struct nss_module *module,
void (*bind) (nss_module_functions_untyped))
{
/* Initialize the function pointers, following the double-checked
locking idiom. */
__libc_lock_lock (nss_module_list_lock);
switch ((enum nss_module_state) atomic_load_acquire (&module->state))
{
case nss_module_uninitialized:
case nss_module_failed:
bind (module->functions.untyped);
#ifdef PTR_MANGLE
for (int i = 0; i < nss_module_functions_count; ++i)
PTR_MANGLE (module->functions.untyped[i]);
#endif
module->handle = NULL;
/* Synchronizes with unlocked __nss_module_load atomic_load_acquire. */
atomic_store_release (&module->state, nss_module_loaded);
break;
case nss_module_loaded:
/* Nothing to clean up. */
break;
}
__libc_lock_unlock (nss_module_list_lock);
return true;
}
/* Loads the built-in nss_files module. */
static bool static bool
module_load_nss_files (struct nss_module *module) module_load_nss_files (struct nss_module *module)
{ {
@ -124,25 +159,14 @@ module_load_nss_files (struct nss_module *module)
_nss_files_init (cb); _nss_files_init (cb);
} }
#endif #endif
return module_load_builtin (module, __nss_files_functions);
}
/* Initialize the function pointers, following the double-checked /* Loads the built-in nss_dns module. */
locking idiom. */ static bool
__libc_lock_lock (nss_module_list_lock); module_load_nss_dns (struct nss_module *module)
switch ((enum nss_module_state) atomic_load_acquire (&module->state)) {
{ return module_load_builtin (module, __nss_dns_functions);
case nss_module_uninitialized:
case nss_module_failed:
__nss_files_functions (module->functions.untyped);
module->handle = NULL;
/* Synchronizes with unlocked __nss_module_load atomic_load_acquire. */
atomic_store_release (&module->state, nss_module_loaded);
break;
case nss_module_loaded:
/* Nothing to clean up. */
break;
}
__libc_lock_unlock (nss_module_list_lock);
return true;
} }
/* Internal implementation of __nss_module_load. */ /* Internal implementation of __nss_module_load. */
@ -151,6 +175,8 @@ module_load (struct nss_module *module)
{ {
if (strcmp (module->name, "files") == 0) if (strcmp (module->name, "files") == 0)
return module_load_nss_files (module); return module_load_nss_files (module);
if (strcmp (module->name, "dns") == 0)
return module_load_nss_dns (module);
void *handle; void *handle;
{ {
@ -398,7 +424,9 @@ __nss_module_freeres (void)
struct nss_module *current = nss_module_list; struct nss_module *current = nss_module_list;
while (current != NULL) while (current != NULL)
{ {
if (current->state == nss_module_loaded && current->handle != NULL) /* Ignore built-in modules (which have a NULL handle). */
if (current->state == nss_module_loaded
&& current->handle != NULL)
__libc_dlclose (current->handle); __libc_dlclose (current->handle);
struct nss_module *next = current->next; struct nss_module *next = current->next;

View File

@ -33,10 +33,16 @@ struct nss_module_functions
#include "function.def" #include "function.def"
}; };
/* Number of elements of the nss_module_functions_untyped array. */
enum
{
nss_module_functions_count = (sizeof (struct nss_module_functions)
/ sizeof (void *))
};
/* Untyped version of struct nss_module_functions, for consistent /* Untyped version of struct nss_module_functions, for consistent
processing purposes. */ processing purposes. */
typedef void *nss_module_functions_untyped[sizeof (struct nss_module_functions) typedef void *nss_module_functions_untyped[nss_module_functions_count];
/ sizeof (void *)];
/* Locate the nss_files functions, as if by dlopen/dlsym. */ /* Locate the nss_files functions, as if by dlopen/dlsym. */
void __nss_files_functions (nss_module_functions_untyped pointers) void __nss_files_functions (nss_module_functions_untyped pointers)

View File

@ -48,6 +48,7 @@ routines := \
ns_name_unpack \ ns_name_unpack \
ns_samename \ ns_samename \
nsap_addr \ nsap_addr \
nss_dns_functions \
res-close \ res-close \
res-name-checking \ res-name-checking \
res-state \ res-state \

View File

@ -0,0 +1,40 @@
/* Direct access for nss_dns functions for NSS module loading.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <nss/nss_module.h>
#include <nss_dns.h>
#include <string.h>
void
__nss_dns_functions (nss_module_functions_untyped pointers)
{
struct nss_module_functions typed =
{
.getcanonname_r = &_nss_dns_getcanonname_r,
.gethostbyname3_r = &_nss_dns_gethostbyname3_r,
.gethostbyname2_r = &_nss_dns_gethostbyname2_r,
.gethostbyname_r = &_nss_dns_gethostbyname_r,
.gethostbyname4_r = &_nss_dns_gethostbyname4_r,
.gethostbyaddr2_r = &_nss_dns_gethostbyaddr2_r,
.gethostbyaddr_r = &_nss_dns_gethostbyaddr_r,
.getnetbyname_r = &_nss_dns_getnetbyname_r,
.getnetbyaddr_r = &_nss_dns_getnetbyaddr_r,
};
memcpy (pointers, &typed, sizeof (nss_module_functions_untyped));
}