nss: Access nss_files through direct references
authorFlorian Weimer <fweimer@redhat.com>
Wed, 7 Jul 2021 16:33:52 +0000 (18:33 +0200)
committerFlorian Weimer <fweimer@redhat.com>
Wed, 7 Jul 2021 16:33:52 +0000 (18:33 +0200)
This partially fixes static-only NSS support (bug 27959): The files
module no longer needs dlopen.  Support for the dns module remains
to be added, and also support for disabling dlopen altogether.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
20 files changed:
include/nss_files.h
nss/Makefile
nss/nss_files/files-XXX.c
nss/nss_files/files-alias.c
nss/nss_files/files-ethers.c
nss/nss_files/files-grp.c
nss/nss_files/files-hosts.c
nss/nss_files/files-init.c
nss/nss_files/files-initgroups.c
nss/nss_files/files-netgrp.c
nss/nss_files/files-network.c
nss/nss_files/files-proto.c
nss/nss_files/files-pwd.c
nss/nss_files/files-rpc.c
nss/nss_files/files-service.c
nss/nss_files/files-sgrp.c
nss/nss_files/files-spwd.c
nss/nss_files_functions.c [new file with mode: 0644]
nss/nss_module.c
nss/nss_module.h

index dd0081a..6190cac 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef _NSS_FILES_H
 #define _NSS_FILES_H
 
+#include <nss.h>
 #include <stdio.h>
 #if IS_IN (libc)
 #include <libc-lock.h>
@@ -134,6 +135,15 @@ libc_hidden_proto (_nss_files_parse_servent)
 libc_hidden_proto (_nss_files_parse_sgent)
 libc_hidden_proto (_nss_files_parse_spent)
 
+NSS_DECLARE_MODULE_FUNCTIONS (files)
+#undef DEFINE_NSS_FUNCTION
+#define DEFINE_NSS_FUNCTION(x) libc_hidden_proto (_nss_files_##x)
+#include <nss/function.def>
+#undef DEFINE_NSS_FUNCTION
+
+void _nss_files_init (void (*cb) (size_t, struct traced_file *));
+libc_hidden_proto (_nss_files_init)
+
 /* Generic implementation of fget*ent_r.  Reads lines from FP until
    EOF or a successful parse into *RESULT using PARSER.  Returns 0 on
    success, ENOENT on EOF, ERANGE on too-small buffer.  */
index 7259e83..63a386a 100644 (file)
@@ -31,7 +31,8 @@ routines              = nsswitch getnssent getnssent_r digits_dots \
                          compat-lookup nss_hash nss_files_fopen \
                          nss_readline nss_parse_line_result \
                          nss_fgetent_r nss_module nss_action \
-                         nss_action_parse nss_database nss_files_data
+                         nss_action_parse nss_database nss_files_data \
+                         nss_files_functions
 
 # These are the databases that go through nss dispatch.
 # Caution: if you add a database here, you must add its real name
index 91553d7..c158a89 100644 (file)
@@ -91,12 +91,14 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen)
 {
   return __nss_files_data_setent (CONCAT (nss_file_, ENTNAME), DATAFILE);
 }
+libc_hidden_def (CONCAT (_nss_files_set,ENTNAME))
 
 enum nss_status
 CONCAT(_nss_files_end,ENTNAME) (void)
 {
   return __nss_files_data_endent (CONCAT (nss_file_, ENTNAME));
 }
+libc_hidden_def (CONCAT (_nss_files_end,ENTNAME))
 \f
 
 /* Parsing the database file into `struct STRUCTURE' data structures.  */
@@ -179,6 +181,7 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
   __nss_files_data_put (data);
   return status;
 }
+libc_hidden_def (CONCAT (_nss_files_get,ENTNAME_r))
 \f
 /* Macro for defining lookup functions for this file-based database.
 
@@ -215,4 +218,5 @@ _nss_files_get##name##_r (proto,                                          \
     }                                                                        \
                                                                              \
   return status;                                                             \
-}
+}                                                                            \
+libc_hidden_def (_nss_files_get##name##_r)
index 75d91e0..8c6e176 100644 (file)
@@ -31,8 +31,6 @@
 #include "nsswitch.h"
 #include <nss_files.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 \f
 /* Maintenance of the stream open on the database file.  For getXXent
    operations the stream needs to be held open across calls, the other
@@ -63,12 +61,14 @@ _nss_files_setaliasent (void)
 {
   return __nss_files_data_setent (nss_file_aliasent, "/etc/aliases");
 }
+libc_hidden_def (_nss_files_setaliasent)
 
 enum nss_status
 _nss_files_endaliasent (void)
 {
   return __nss_files_data_endent (nss_file_aliasent);
 }
+libc_hidden_def (_nss_files_endaliasent)
 \f
 /* Parsing the database file into `struct aliasent' data structures.  */
 static enum nss_status
@@ -354,7 +354,7 @@ _nss_files_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen,
   __nss_files_data_put (data);
   return status;
 }
-
+libc_hidden_def (_nss_files_getaliasent_r)
 
 enum nss_status
 _nss_files_getaliasbyname_r (const char *name, struct aliasent *result,
@@ -387,3 +387,4 @@ _nss_files_getaliasbyname_r (const char *name, struct aliasent *result,
 
   return status;
 }
+libc_hidden_def (_nss_files_getaliasbyname_r)
index 2fe7f81..7c2c2b9 100644 (file)
@@ -20,8 +20,6 @@
 #include <netinet/if_ether.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 struct etherent_data {};
 
 #define ENTNAME                etherent
index 49be38e..a716d94 100644 (file)
@@ -19,8 +19,6 @@
 #include <grp.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define STRUCTURE      group
 #define ENTNAME                grent
 #define DATABASE       "group"
index 894b85d..d54d91d 100644 (file)
@@ -26,8 +26,6 @@
 #include <alloc_buffer.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 /* Get implementation for some internal functions.  */
 #include "../resolv/res_hconf.h"
 
@@ -358,6 +356,7 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
 
   return status;
 }
+libc_hidden_def (_nss_files_gethostbyname3_r)
 
 enum nss_status
 _nss_files_gethostbyname_r (const char *name, struct hostent *result,
@@ -367,6 +366,7 @@ _nss_files_gethostbyname_r (const char *name, struct hostent *result,
   return _nss_files_gethostbyname3_r (name, AF_INET, result, buffer, buflen,
                                      errnop, herrnop, NULL, NULL);
 }
+libc_hidden_def (_nss_files_gethostbyname_r)
 
 enum nss_status
 _nss_files_gethostbyname2_r (const char *name, int af, struct hostent *result,
@@ -376,6 +376,7 @@ _nss_files_gethostbyname2_r (const char *name, int af, struct hostent *result,
   return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen,
                                      errnop, herrnop, NULL, NULL);
 }
+libc_hidden_def (_nss_files_gethostbyname2_r)
 
 enum nss_status
 _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
@@ -491,3 +492,4 @@ _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
 
   return status;
 }
+libc_hidden_def (_nss_files_gethostbyname4_r)
index 717c9fd..18ed288 100644 (file)
@@ -21,8 +21,7 @@
 #include <string.h>
 #include <nscd/nscd.h>
 #include <nss.h>
-
-NSS_DECLARE_MODULE_FUNCTIONS (files)
+#include <nss_files.h>
 
 static void
 register_file (void (*cb) (size_t, struct traced_file *),
@@ -49,5 +48,6 @@ _nss_files_init (void (*cb) (size_t, struct traced_file *))
   register_file (cb, servdb, "/etc/services", 0);
   register_file (cb, netgrdb, "/etc/netgroup", 0);
 }
+libc_hidden_def (_nss_files_init)
 
 #endif
index 6fcea40..b44211e 100644 (file)
@@ -28,8 +28,6 @@
 #include <nss.h>
 #include <nss_files.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 enum nss_status
 _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
                           long int *size, gid_t **groupsp, long int limit,
@@ -129,3 +127,4 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
 
   return status == NSS_STATUS_SUCCESS && !any ? NSS_STATUS_NOTFOUND : status;
 }
+libc_hidden_def (_nss_files_initgroups_dyn)
index be9c72a..75bfbd9 100644 (file)
@@ -28,8 +28,6 @@
 #include "netgroup.h"
 #include <nss_files.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define DATAFILE       "/etc/netgroup"
 
 libc_hidden_proto (_nss_files_endnetgrent)
@@ -152,7 +150,7 @@ _nss_files_setnetgrent (const char *group, struct __netgrent *result)
 
   return status;
 }
-
+libc_hidden_def (_nss_files_setnetgrent)
 
 enum nss_status
 _nss_files_endnetgrent (struct __netgrent *result)
@@ -293,3 +291,4 @@ _nss_files_getnetgrent_r (struct __netgrent *result, char *buffer,
 
   return status;
 }
+libc_hidden_def (_nss_files_getnetgrent_r)
index 75c9f8a..217ed78 100644 (file)
@@ -21,7 +21,6 @@
 #include <netdb.h>
 #include <stdint.h>
 #include <nss.h>
-#include <nss_files.h>
 
 #define ENTNAME                netent
 #define DATABASE       "networks"
index 98d082c..1307269 100644 (file)
@@ -19,8 +19,6 @@
 #include <netdb.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define ENTNAME                protoent
 #define DATABASE       "protocols"
 
index b04165d..5c74c6d 100644 (file)
@@ -19,8 +19,6 @@
 #include <pwd.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define STRUCTURE      passwd
 #define ENTNAME                pwent
 #define DATABASE       "passwd"
index eeb2725..3dea8f1 100644 (file)
@@ -19,8 +19,6 @@
 #include <rpc/netdb.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define ENTNAME                rpcent
 #define DATABASE       "rpc"
 
index f4f0985..a8d83e0 100644 (file)
@@ -20,8 +20,6 @@
 #include <netdb.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define ENTNAME                servent
 #define DATABASE       "services"
 
index 6b1c9ea..213a408 100644 (file)
@@ -19,8 +19,6 @@
 #include <gshadow.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define STRUCTURE      sgrp
 #define ENTNAME                sgent
 #define DATABASE       "gshadow"
index 976deaf..d031257 100644 (file)
@@ -19,8 +19,6 @@
 #include <shadow.h>
 #include <nss.h>
 
-NSS_DECLARE_MODULE_FUNCTIONS (files)
-
 #define STRUCTURE      spwd
 #define ENTNAME                spent
 #define DATABASE       "shadow"
diff --git a/nss/nss_files_functions.c b/nss/nss_files_functions.c
new file mode 100644 (file)
index 0000000..85720b4
--- /dev/null
@@ -0,0 +1,43 @@
+/* Direct access for nss_files 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_module.h>
+#include <nss_files.h>
+
+void
+__nss_files_functions (nss_module_functions_untyped pointers)
+{
+  void **fptr = pointers;
+
+  /* Functions which are not implemented.  */
+#define _nss_files_getcanonname_r NULL
+#define _nss_files_gethostbyaddr2_r NULL
+#define _nss_files_getpublickey NULL
+#define _nss_files_getsecretkey NULL
+#define _nss_files_netname2user NULL
+
+#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
+}
index 60c070c..7b42c58 100644 (file)
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <nss_files.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
@@ -110,10 +111,45 @@ static const function_name nss_function_name_array[] =
 #include "function.def"
   };
 
+static bool
+module_load_nss_files (struct nss_module *module)
+{
+  if (is_nscd)
+    {
+      void (*cb) (size_t, struct traced_file *) = nscd_init_cb;
+#  ifdef PTR_DEMANGLE
+      PTR_DEMANGLE (cb);
+#  endif
+      _nss_files_init (cb);
+    }
+
+  /* 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:
+      __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.  */
 static bool
 module_load (struct nss_module *module)
 {
+  if (strcmp (module->name, "files") == 0)
+    return module_load_nss_files (module);
+
   void *handle;
   {
     char *shlib_name;
@@ -360,7 +396,7 @@ __nss_module_freeres (void)
   struct nss_module *current = nss_module_list;
   while (current != NULL)
     {
-      if (current->state == nss_module_loaded)
+      if (current->state == nss_module_loaded && current->handle != NULL)
         __libc_dlclose (current->handle);
 
       struct nss_module *next = current->next;
index 05c4791..c1a1d90 100644 (file)
@@ -38,6 +38,10 @@ struct nss_module_functions
 typedef void *nss_module_functions_untyped[sizeof (struct nss_module_functions)
                                            / sizeof (void *)];
 
+/* Locate the nss_files functions, as if by dlopen/dlsym.  */
+void __nss_files_functions (nss_module_functions_untyped pointers)
+  attribute_hidden;
+
 /* Initialization state of a NSS module.  */
 enum nss_module_state
 {