]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
nss: Introduce dedicated struct nss_database_for_fork type
authorFlorian Weimer <fweimer@redhat.com>
Fri, 13 Feb 2026 08:02:07 +0000 (09:02 +0100)
committerFlorian Weimer <fweimer@redhat.com>
Fri, 13 Feb 2026 08:02:07 +0000 (09:02 +0100)
The initialized field in struct nss_database_data is rather confusing
because it is not used by the regular NSS code, only by the fork
state synchronization code.  Introduce a separate type and place
the initialized field there.

Reviewed-by: Sam James <sam@gentoo.org>
nss/nss_database.c
nss/nss_database.h
posix/fork.c

index 6997b5bb04ff52a750eb59131b192fe5e1e67670..19e752ef6572444bdc1ff1f82bf98a4027eae470 100644 (file)
@@ -56,7 +56,6 @@ global_state_allocate (void *closure)
     {
       result->data.nsswitch_conf.size = -1; /* Force reload.  */
       memset (result->data.services, 0, sizeof (result->data.services));
-      result->data.initialized = true;
       result->data.reload_disabled = false;
       __libc_lock_init (result->lock);
       result->root_ino = 0;
@@ -439,8 +438,8 @@ nss_database_check_reload_and_get (struct nss_database_state *local,
   /* Avoid overwriting the global configuration until we have loaded
      everything successfully.  Otherwise, if the file change
      information changes back to what is in the global configuration,
-     the lookups would use the partially-written  configuration.  */
-  struct nss_database_data staging = { .initialized = true, };
+     the lookups would use the partially-written configuration.  */
+  struct nss_database_data staging = { };
 
   bool ok = nss_database_reload (&staging, &initial);
 
@@ -491,7 +490,7 @@ __nss_database_freeres (void)
 }
 
 void
-__nss_database_fork_prepare_parent (struct nss_database_data *data)
+__nss_database_fork_prepare_parent (struct nss_database_for_fork *data)
 {
   /* Do not use allocate_once to trigger loading unnecessarily.  */
   struct nss_database_state *local = atomic_load_acquire (&global_database_state);
@@ -503,20 +502,21 @@ __nss_database_fork_prepare_parent (struct nss_database_data *data)
          because it avoids acquiring the lock during the actual
          fork.  */
       __libc_lock_lock (local->lock);
-      *data = local->data;
+      data->data = local->data;
       __libc_lock_unlock (local->lock);
+      data->initialized = true;
     }
 }
 
 void
-__nss_database_fork_subprocess (struct nss_database_data *data)
+__nss_database_fork_subprocess (struct nss_database_for_fork *data)
 {
   struct nss_database_state *local = atomic_load_acquire (&global_database_state);
   if (data->initialized)
     {
       /* Restore the state at the point of the fork.  */
       assert (local != NULL);
-      local->data = *data;
+      local->data = data->data;
       __libc_lock_init (local->lock);
     }
   else if (local != NULL)
index 1f2ff1639abe13632a8504af400520f6a70c87fc..a4f3369eb0d0f451be2c707e745605c92c906bd6 100644 (file)
@@ -70,15 +70,21 @@ struct nss_database_data
   struct file_change_detection nsswitch_conf;
   nss_action_list services[NSS_DATABASE_COUNT];
   int reload_disabled;          /* Actually bool; int for atomic access.  */
-  bool initialized;
+};
+
+/* Use to store a consistent state snapshot across fork.  */
+struct nss_database_for_fork
+{
+  bool initialized;  /* Set to true if the data field below is initialized.  */
+  struct nss_database_data data;
 };
 
 /* Called by fork in the parent process, before forking.  */
-void __nss_database_fork_prepare_parent (struct nss_database_data *data)
+void __nss_database_fork_prepare_parent (struct nss_database_for_fork *)
   attribute_hidden;
 
 /* Called by fork in the new subprocess, after forking.  */
-void __nss_database_fork_subprocess (struct nss_database_data *data)
+void __nss_database_fork_subprocess (struct nss_database_for_fork *)
   attribute_hidden;
 
 #endif /* _NSS_DATABASE_H */
index 8e541ff98564e286535e8ea1c6372a7590b9640b..933ac6fee741ce0e4e92c5f808845b4f00d93f77 100644 (file)
@@ -50,7 +50,7 @@ __libc_fork (void)
 
   lastrun = __run_prefork_handlers (multiple_threads);
 
-  struct nss_database_data nss_database_data;
+  struct nss_database_for_fork nss_database_data;
 
   /* If we are not running multiple threads, we do not have to
      preserve lock state.  If fork runs from a signal handler, only