Stop receiving child callbacks in a child libctx when appropriate
authorMatt Caswell <matt@openssl.org>
Tue, 9 Nov 2021 13:48:31 +0000 (13:48 +0000)
committerMatt Caswell <matt@openssl.org>
Fri, 12 Nov 2021 17:16:14 +0000 (17:16 +0000)
We should stop receiving child callbacks if we're about to free up
the child libctx. Otherwise we can get callbacks when the libctx is half
freed up.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16980)

crypto/context.c
crypto/provider_child.c
doc/internal/man3/ossl_provider_new.pod
include/internal/provider.h

index 1e0dfa8e015e35d0d0bc5a13863db54a959a00f0..bba8e4208b1a0b436282456256ffee6d44f6a719 100644 (file)
@@ -240,6 +240,10 @@ void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx)
     if (ossl_lib_ctx_is_default(ctx))
         return;
 
+#ifndef FIPS_MODULE
+    if (ctx->ischild)
+        ossl_provider_deinit_child(ctx);
+#endif
     context_deinit(ctx);
     OPENSSL_free(ctx);
 }
index 1b925303010747cdaebefb5e7816e73b55737f03..977ea4db3bf2155f69cb771b827a8df3092d6ad3 100644 (file)
@@ -42,7 +42,6 @@ static void child_prov_ossl_ctx_free(void *vgbl)
 {
     struct child_prov_globals *gbl = vgbl;
 
-    gbl->c_provider_deregister_child_cb(gbl->handle);
     CRYPTO_THREAD_lock_free(gbl->lock);
     OPENSSL_free(gbl);
 }
@@ -269,6 +268,17 @@ int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
     return 1;
 }
 
+void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx)
+{
+    struct child_prov_globals *gbl
+        = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+                                &child_prov_ossl_ctx_method);
+    if (gbl == NULL)
+        return;
+
+    gbl->c_provider_deregister_child_cb(gbl->handle);
+}
+
 int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate)
 {
     struct child_prov_globals *gbl;
index 7f6934a59e38ae599d2c349c8d6e47cc90db43cb..1dba1860f7573f532d7e0e105aa1b26240e45e99 100644 (file)
@@ -8,7 +8,7 @@ ossl_provider_set_module_path,
 ossl_provider_add_parameter, ossl_provider_set_child, ossl_provider_get_parent,
 ossl_provider_up_ref_parent, ossl_provider_free_parent,
 ossl_provider_default_props_update, ossl_provider_get0_dispatch,
-ossl_provider_init_as_child,
+ossl_provider_init_as_child, ossl_provider_deinit_child,
 ossl_provider_activate, ossl_provider_deactivate, ossl_provider_add_to_store,
 ossl_provider_ctx,
 ossl_provider_doall_activated,
@@ -98,7 +98,7 @@ ossl_provider_get_capabilities
  int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
                                  const OSSL_CORE_HANDLE *handle,
                                  const OSSL_DISPATCH *in);
-
+ void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx);
 
 =head1 DESCRIPTION
 
@@ -302,6 +302,10 @@ the necessary upcalls for managing child providers. The I<handle> and I<in>
 parameters are the B<OSSL_CORE_HANDLE> and B<OSSL_DISPATCH> pointers that were
 passed to the provider's B<OSSL_provider_init> function.
 
+ossl_provider_deinit_child() deregisters callbacks from the parent library
+context about provider creation or removal events for the child library context
+I<ctx>. Must only be called if I<ctx> is a child library context.
+
 =head1 NOTES
 
 Locating a provider module happens as follows:
index ae8d7434374ddf39948c73044a734af417f61f05..b8ba7f689267611b2aa62cc605d33e765b942263 100644 (file)
@@ -107,6 +107,7 @@ void ossl_provider_add_conf_module(void);
 int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
                                 const OSSL_CORE_HANDLE *handle,
                                 const OSSL_DISPATCH *in);
+void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx);
 
 # ifdef __cplusplus
 }