summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2020-06-19 15:05:37 -0400
committerGreg Hudson <ghudson@mit.edu>2020-11-03 11:32:15 -0500
commit75ae7431dbefc4b2ec082a4cfe3f65749fde0fda (patch)
tree0d04269d8eaacff018b048ff7f064410aed0d69a
parent3c4075b01375c04070f991920028ce9117f2a512 (diff)
downloadkrb5-75ae7431dbefc4b2ec082a4cfe3f65749fde0fda.tar.gz
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. (cherry picked from commit 38b98a14433b8858a3ca5979a0afa194df0df1e9) ticket: 8918 version_fixed: 1.17.2
-rw-r--r--src/kadmin/server/misc.c4
-rw-r--r--src/kadmin/server/ovsec_kadmd.c15
-rw-r--r--src/kadmin/server/schpw.c4
-rw-r--r--src/kdc/main.c11
-rw-r--r--src/lib/kadm5/srv/server_kdb.c2
5 files changed, 26 insertions, 10 deletions
diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
index 45e1f81a5..2d596e27f 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 6a6b21401..159a5c398 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, &params,
+ 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 f7dea3996..00465657a 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 408c723f5..26bf9f410 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -1011,9 +1011,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) {
@@ -1025,16 +1029,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 f4b8aef2b..eb818778f 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;