113 lines
4.3 KiB
Diff
113 lines
4.3 KiB
Diff
commit 7bb859f4198d0be19c31a9937eae4f6c2c9a079e
|
|
Author: Florian Weimer <fweimer@redhat.com>
|
|
Date: Fri Feb 13 09:02:07 2026 +0100
|
|
|
|
nss: Introduce dedicated struct nss_database_for_fork type
|
|
|
|
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>
|
|
|
|
diff --git a/nss/nss_database.c b/nss/nss_database.c
|
|
index e807e9d84ca03680..293e8457d70c00ba 100644
|
|
--- a/nss/nss_database.c
|
|
+++ b/nss/nss_database.c
|
|
@@ -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;
|
|
@@ -451,8 +450,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);
|
|
|
|
@@ -503,7 +502,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);
|
|
@@ -515,20 +514,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)
|
|
diff --git a/nss/nss_database.h b/nss/nss_database.h
|
|
index d4b23b5295110c1c..349a793a6ef011e4 100644
|
|
--- a/nss/nss_database.h
|
|
+++ b/nss/nss_database.h
|
|
@@ -73,15 +73,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 */
|
|
diff --git a/posix/fork.c b/posix/fork.c
|
|
index 5a5baf63aa971b43..b996f4c63acc4e4b 100644
|
|
--- a/posix/fork.c
|
|
+++ b/posix/fork.c
|
|
@@ -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
|