]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Avoid using LMDB environments across forks
authorGreg Hudson <ghudson@mit.edu>
Fri, 19 Jun 2020 19:05:37 +0000 (15:05 -0400)
committerGreg Hudson <ghudson@mit.edu>
Tue, 3 Nov 2020 16:32:15 +0000 (11:32 -0500)
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

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 6a6b21401ef333bcb579ab4210bcbd302fb86d46..159a5c39806d2b7490e395bce812a3c9afa0ade0 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 408c723f52f09f243a5c8e2db52982fc1d7891e6..26bf9f410bb91356ee4e0a1ebd789b322035d84b 100644 (file)
@@ -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) {
index f4b8aef2bde1c018b293be0fd1f6482c29ff6da6..eb818778f046c8e6d9535948e81a97885e104074 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;