aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2021-07-19 07:55:27 +0200
committerFlorian Weimer <fweimer@redhat.com>2021-07-19 07:56:57 +0200
commitee5ed99922ca90bcea4a2f9a48a0c9ae4b534ece (patch)
treefd5d30e2d8a6f676f63698560094da119108806c
parente1fcf21474c5b522fdad4ac0191d5dcc3271dba6 (diff)
downloadglibc-ee5ed99922ca90bcea4a2f9a48a0c9ae4b534ece.zip
glibc-ee5ed99922ca90bcea4a2f9a48a0c9ae4b534ece.tar.gz
glibc-ee5ed99922ca90bcea4a2f9a48a0c9ae4b534ece.tar.bz2
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>
-rw-r--r--include/nss_dns.h13
-rw-r--r--nss/nss_files_functions.c6
-rw-r--r--nss/nss_module.c58
-rw-r--r--nss/nss_module.h10
-rw-r--r--resolv/Makefile1
-rw-r--r--resolv/nss_dns_functions.c40
6 files changed, 100 insertions, 28 deletions
diff --git a/include/nss_dns.h b/include/nss_dns.h
index 63b5853..53205b2 100644
--- a/include/nss_dns.h
+++ b/include/nss_dns.h
@@ -24,13 +24,16 @@
NSS_DECLARE_MODULE_FUNCTIONS (dns)
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_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_getnetbyname_r)
+
+void __nss_dns_functions (nss_module_functions_untyped pointers)
+ attribute_hidden;
#endif
diff --git a/nss/nss_files_functions.c b/nss/nss_files_functions.c
index 85720b4..46040ff 100644
--- a/nss/nss_files_functions.c
+++ b/nss/nss_files_functions.c
@@ -34,10 +34,4 @@ __nss_files_functions (nss_module_functions_untyped pointers)
#undef DEFINE_NSS_FUNCTION
#define DEFINE_NSS_FUNCTION(x) *fptr++ = _nss_files_##x;
#include "function.def"
-
-#ifdef PTR_MANGLE
- void **end = fptr;
- for (fptr = pointers; fptr != end; ++fptr)
- PTR_MANGLE (*fptr);
-#endif
}
diff --git a/nss/nss_module.c b/nss/nss_module.c
index 7ea5ad9..b28cb94 100644
--- a/nss/nss_module.c
+++ b/nss/nss_module.c
@@ -26,11 +26,13 @@
#include <dlfcn.h>
#include <gnu/lib-names.h>
#include <libc-lock.h>
+#include <nss_dns.h>
+#include <nss_files.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <nss_files.h>
+#include <sysdep.h>
/* 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
@@ -111,20 +113,12 @@ static const function_name nss_function_name_array[] =
#include "function.def"
};
+/* Loads a built-in module, binding the symbols using the supplied
+ callback function. Always returns true. */
static bool
-module_load_nss_files (struct nss_module *module)
+module_load_builtin (struct nss_module *module,
+ void (*bind) (nss_module_functions_untyped))
{
-#ifdef USE_NSCD
- if (is_nscd)
- {
- void (*cb) (size_t, struct traced_file *) = nscd_init_cb;
-# ifdef PTR_DEMANGLE
- PTR_DEMANGLE (cb);
-# endif
- _nss_files_init (cb);
- }
-#endif
-
/* Initialize the function pointers, following the double-checked
locking idiom. */
__libc_lock_lock (nss_module_list_lock);
@@ -132,7 +126,13 @@ module_load_nss_files (struct nss_module *module)
{
case nss_module_uninitialized:
case nss_module_failed:
- __nss_files_functions (module->functions.untyped);
+ 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);
@@ -145,12 +145,38 @@ module_load_nss_files (struct nss_module *module)
return true;
}
+/* Loads the built-in nss_files module. */
+static bool
+module_load_nss_files (struct nss_module *module)
+{
+#ifdef USE_NSCD
+ if (is_nscd)
+ {
+ void (*cb) (size_t, struct traced_file *) = nscd_init_cb;
+# ifdef PTR_DEMANGLE
+ PTR_DEMANGLE (cb);
+# endif
+ _nss_files_init (cb);
+ }
+#endif
+ return module_load_builtin (module, __nss_files_functions);
+}
+
+/* Loads the built-in nss_dns module. */
+static bool
+module_load_nss_dns (struct nss_module *module)
+{
+ return module_load_builtin (module, __nss_dns_functions);
+}
+
/* Internal implementation of __nss_module_load. */
static bool
module_load (struct nss_module *module)
{
if (strcmp (module->name, "files") == 0)
return module_load_nss_files (module);
+ if (strcmp (module->name, "dns") == 0)
+ return module_load_nss_dns (module);
void *handle;
{
@@ -398,7 +424,9 @@ __nss_module_freeres (void)
struct nss_module *current = nss_module_list;
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);
struct nss_module *next = current->next;
diff --git a/nss/nss_module.h b/nss/nss_module.h
index c1a1d90..b52c293 100644
--- a/nss/nss_module.h
+++ b/nss/nss_module.h
@@ -33,10 +33,16 @@ struct nss_module_functions
#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
processing purposes. */
-typedef void *nss_module_functions_untyped[sizeof (struct nss_module_functions)
- / sizeof (void *)];
+typedef void *nss_module_functions_untyped[nss_module_functions_count];
/* Locate the nss_files functions, as if by dlopen/dlsym. */
void __nss_files_functions (nss_module_functions_untyped pointers)
diff --git a/resolv/Makefile b/resolv/Makefile
index dd0a98c..31d2745 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -48,6 +48,7 @@ routines := \
ns_name_unpack \
ns_samename \
nsap_addr \
+ nss_dns_functions \
res-close \
res-name-checking \
res-state \
diff --git a/resolv/nss_dns_functions.c b/resolv/nss_dns_functions.c
new file mode 100644
index 0000000..158dafe
--- /dev/null
+++ b/resolv/nss_dns_functions.c
@@ -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));
+}