diff options
author | Greg Hudson <ghudson@mit.edu> | 2020-06-19 15:05:37 -0400 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2020-11-03 11:32:15 -0500 |
commit | 75ae7431dbefc4b2ec082a4cfe3f65749fde0fda (patch) | |
tree | 0d04269d8eaacff018b048ff7f064410aed0d69a | |
parent | 3c4075b01375c04070f991920028ce9117f2a512 (diff) | |
download | krb5-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.c | 4 | ||||
-rw-r--r-- | src/kadmin/server/ovsec_kadmd.c | 15 | ||||
-rw-r--r-- | src/kadmin/server/schpw.c | 4 | ||||
-rw-r--r-- | src/kdc/main.c | 11 | ||||
-rw-r--r-- | 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 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, ¶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 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; |