krb5 commit: Avoid using LMDB environments across forks
Greg Hudson
ghudson at mit.edu
Tue Jul 7 00:39:24 EDT 2020
https://github.com/krb5/krb5/commit/38b98a14433b8858a3ca5979a0afa194df0df1e9
commit 38b98a14433b8858a3ca5979a0afa194df0df1e9
Author: Greg Hudson <ghudson at mit.edu>
Date: Fri Jun 19 15:05:37 2020 -0400
Avoid using LMDB environments across forks
In krb5kdc and kadmind, reinitialize the DB state after daemonizing,
to prevent using an LMDB environment in a different process than it
was created. Otherwise the daemon's reader table slot appears to be
stale and can be claimed by another process.
In kadmind, this change means that global_server_handle changes value
after the loop setup. Add an extra level of pointer indirection so
that the handle passed to the loop remains valid.
kdb_init_hist() is now called twice by kadmind. Change it to avoid
leaking hist_princ on the second invocation.
ticket: 8918
tags: pullup
target_version: 1.18-next
target_version: 1.17-next
src/kadmin/server/misc.c | 4 ++--
src/kadmin/server/ovsec_kadmd.c | 15 +++++++++++++--
src/kadmin/server/schpw.c | 4 ++--
src/kdc/main.c | 11 +++++++----
src/lib/kadm5/srv/server_kdb.c | 2 ++
5 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
index 45e1f81..2d596e2 100644
--- a/src/kadmin/server/misc.c
+++ b/src/kadmin/server/misc.c
@@ -136,7 +136,7 @@ make_toolong_error (void *handle, krb5_data **out)
krb5_error errpkt;
krb5_error_code retval;
krb5_data *scratch;
- kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
+ kadm5_server_handle_t server_handle = *(void **)handle;
retval = krb5_us_timeofday(server_handle->context, &errpkt.stime, &errpkt.susec);
if (retval)
@@ -170,6 +170,6 @@ make_toolong_error (void *handle, krb5_data **out)
krb5_context get_context(void *handle)
{
- kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
+ kadm5_server_handle_t server_handle = *(void **)handle;
return server_handle->context;
}
diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c
index 3737791..6305e83 100644
--- a/src/kadmin/server/ovsec_kadmd.c
+++ b/src/kadmin/server/ovsec_kadmd.c
@@ -144,7 +144,7 @@ setup_loop(kadm5_config_params *params, int proponly, verto_ctx **ctx_out)
*ctx_out = ctx = loop_init(VERTO_EV_TYPE_SIGNAL);
if (ctx == NULL)
return ENOMEM;
- ret = loop_setup_signals(ctx, global_server_handle, NULL);
+ ret = loop_setup_signals(ctx, &global_server_handle, NULL);
if (ret)
return ret;
if (!proponly) {
@@ -171,7 +171,7 @@ setup_loop(kadm5_config_params *params, int proponly, verto_ctx **ctx_out)
return ret;
}
#endif
- return loop_setup_network(ctx, global_server_handle, progname,
+ return loop_setup_network(ctx, &global_server_handle, progname,
DEFAULT_TCP_LISTEN_BACKLOG);
}
@@ -511,6 +511,11 @@ main(int argc, char *argv[])
if (ret)
fail_to_start(ret, _("initializing ACL file"));
+ /* Since some KDB modules are not fork-safe, we must reinitialize the
+ * server handle after daemonizing. */
+ kadm5_destroy(global_server_handle);
+ global_server_handle = NULL;
+
if (!nofork && daemon(0, 0) != 0)
fail_to_start(errno, _("spawning daemon process"));
if (pid_file != NULL) {
@@ -519,6 +524,12 @@ main(int argc, char *argv[])
fail_to_start(ret, _("creating PID file"));
}
+ ret = kadm5_init(context, "kadmind", NULL, NULL, ¶ms,
+ KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args,
+ &global_server_handle);
+ if (ret)
+ fail_to_start(ret, _("initializing"));
+
krb5_klog_syslog(LOG_INFO, _("Seeding random number generator"));
ret = krb5_c_random_os_entropy(context, strong_random, NULL);
if (ret)
diff --git a/src/kadmin/server/schpw.c b/src/kadmin/server/schpw.c
index f7dea39..0046565 100644
--- a/src/kadmin/server/schpw.c
+++ b/src/kadmin/server/schpw.c
@@ -436,7 +436,7 @@ dispatch(void *handle, const krb5_fulladdr *local_addr,
{
krb5_error_code ret;
krb5_keytab kt = NULL;
- kadm5_server_handle_t server_handle = (kadm5_server_handle_t)handle;
+ kadm5_server_handle_t server_handle = *(void **)handle;
krb5_data *response = NULL;
const char *emsg;
@@ -454,7 +454,7 @@ dispatch(void *handle, const krb5_fulladdr *local_addr,
goto egress;
ret = process_chpw_request(server_handle->context,
- handle,
+ server_handle,
server_handle->params.realm,
kt,
local_addr,
diff --git a/src/kdc/main.c b/src/kdc/main.c
index b845710..27aa10d 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -1025,9 +1025,13 @@ int main(int argc, char **argv)
finish_realms();
return 1;
}
+
+ /* Clean up realms for now and reinitialize them after daemonizing, since
+ * some KDB modules are not fork-safe. */
+ finish_realms();
+
if (!nofork && daemon(0, 0)) {
kdc_err(kcontext, errno, _("while detaching from tty"));
- finish_realms();
return 1;
}
if (pid_file != NULL) {
@@ -1039,16 +1043,15 @@ int main(int argc, char **argv)
}
}
if (workers > 0) {
- finish_realms();
retval = create_workers(ctx, workers);
if (retval) {
kdc_err(kcontext, errno, _("creating worker processes"));
return 1;
}
- /* We get here only in a worker child process; re-initialize realms. */
- initialize_realms(kcontext, argc, argv, NULL);
}
+ initialize_realms(kcontext, argc, argv, NULL);
+
/* Initialize audit system and audit KDC startup. */
retval = load_audit_modules(kcontext);
if (retval) {
diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c
index 0ddfa4c..2ec80a0 100644
--- a/src/lib/kadm5/srv/server_kdb.c
+++ b/src/lib/kadm5/srv/server_kdb.c
@@ -127,6 +127,8 @@ krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
goto done;
}
+ krb5_free_principal(handle->context, hist_princ);
+ hist_princ = NULL;
if ((ret = krb5_parse_name(handle->context, hist_name, &hist_princ)))
goto done;
More information about the cvs-krb5
mailing list