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

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/75ae7431dbefc4b2ec082a4cfe3f65749fde0fda
commit 75ae7431dbefc4b2ec082a4cfe3f65749fde0fda
Author: Greg Hudson <[email protected]>
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.17.2

 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 6a6b214..159a5c3 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 408c723..26bf9f4 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 f4b8aef..eb81877 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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.