krb5 commit [krb5-1.18]: Avoid using LMDB environments across forks

Greg Hudson ghudson at mit.edu
Tue Nov 3 13:14:26 EST 2020


https://github.com/krb5/krb5/commit/146245e98795757effee893f9098f8e73131a902
commit 146245e98795757effee893f9098f8e73131a902
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri Jun 19 15:05:37 2020 -0400

    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.18.3

 src/kadmin/server/misc.c        |    4 ++--
 src/kadmin/server/ovsec_kadmd.c |   15 +++++++++++++--
 src/kadmin/server/schpw.c       |    4 ++--
 src/kdc/main.c                  |   11 +++++++----
 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 45e1f81..2d596e2 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 3737791..6305e83 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 f7dea39..0046565 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 fdcd694..38d76b3 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -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) {
diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c
index 0ddfa4c..2ec80a0 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;
 


More information about the cvs-krb5 mailing list