]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Avoid using LMDB environments across forks 1088/head
authorGreg Hudson <ghudson@mit.edu>
Fri, 19 Jun 2020 19:05:37 +0000 (15:05 -0400)
committerGreg Hudson <ghudson@mit.edu>
Mon, 6 Jul 2020 20:18:28 +0000 (16:18 -0400)
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
src/kadmin/server/ovsec_kadmd.c
src/kadmin/server/schpw.c
src/kdc/main.c
src/lib/kadm5/srv/server_kdb.c

index 45e1f81a52503624585a823b98c181f33ed1c40d..2d596e27f8b7c6b02654864d6bb43a45b757a4fd 100644 (file)
@@ -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;
 }
index 3737791b6632d180dc6dff271fa8a369ae67c735..6305e8372b698a465a44be767f0f6940d06e57ec 100644 (file)
@@ -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)
index f7dea399618747259583ecebbb52cd628f9c6dd1..00465657a9a42b5b3e9a9c7fff78f0ad0f41a43c 100644 (file)
@@ -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,
index b845710fa6e1f44ce0dbb1b4a87cf2225c405017..27aa10da0d804dd26519c5531770de48b6393389 100644 (file)
@@ -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) {
index 0ddfa4c077807a3a6ae0d8c1c91da70693e7dacb..2ec80a0f2b0e2ffeb6210aed54c6d7950adf839b 100644 (file)
@@ -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;