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
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)
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;
}
*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) {
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);
}
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) {
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)
{
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;
goto egress;
ret = process_chpw_request(server_handle->context,
- handle,
+ server_handle,
server_handle->params.realm,
kt,
local_addr,
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) {
}
}
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) {
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;