From dea8452218781394ee0256604132197fe43b7d61 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 6 Sep 2023 15:34:03 -0400 Subject: [PATCH] Reinit module only once after fork This prevent multiple threads from stomping on each other and reinit the module multiple times. Fixes #281 Signed-off-by: Simo Sorce --- src/interface.c | 15 +++++++++++++++ src/interface.h | 1 + src/provider.c | 1 + 3 files changed, 17 insertions(+) diff --git a/src/interface.c b/src/interface.c index 7ff1f542..6efa3173 100644 --- a/src/interface.c +++ b/src/interface.c @@ -23,6 +23,7 @@ struct p11prov_module_ctx { pthread_mutex_t lock; bool initialized; + bool reinit; }; /* This structure is effectively equivalent to CK_FUNCTION_LIST_3_0 @@ -364,6 +365,12 @@ void p11prov_module_free(P11PROV_MODULE *mctx) OPENSSL_free(mctx); } +/* should only be called by the fork handler */ +void p11prov_module_mark_reinit(P11PROV_MODULE *mctx) +{ + mctx->reinit = true; +} + CK_RV p11prov_module_reinit(P11PROV_MODULE *mctx) { CK_C_INITIALIZE_ARGS args = { 0 }; @@ -380,6 +387,11 @@ CK_RV p11prov_module_reinit(P11PROV_MODULE *mctx) } /* LOCKED SECTION ------------- */ + if (!mctx->reinit) { + /* another thread already did it */ + goto done; + } + P11PROV_debug("PKCS#11: Re-initializing the module: %s", mctx->path); (void)p11prov_Finalize(mctx->provctx, NULL); @@ -395,6 +407,9 @@ CK_RV p11prov_module_reinit(P11PROV_MODULE *mctx) goto done; } + /* clear reinit flag as we just did re-initialize */ + mctx->reinit = false; + ret = p11prov_GetInfo(mctx->provctx, &ck_info); if (ret != CKR_OK) { goto done; diff --git a/src/interface.h b/src/interface.h index bef6ea36..535b885f 100644 --- a/src/interface.h +++ b/src/interface.h @@ -17,6 +17,7 @@ CK_RV p11prov_module_new(P11PROV_CTX *ctx, const char *path, CK_RV p11prov_module_init(P11PROV_MODULE *mctx); P11PROV_INTERFACE *p11prov_module_get_interface(P11PROV_MODULE *mctx); void p11prov_module_free(P11PROV_MODULE *mctx); +void p11prov_module_mark_reinit(P11PROV_MODULE *mctx); CK_RV p11prov_module_reinit(P11PROV_MODULE *mctx); CK_RV p11prov_Initialize(P11PROV_CTX *ctx, CK_VOID_PTR pInitArgs); CK_RV p11prov_Finalize(P11PROV_CTX *ctx, CK_VOID_PTR pReserved); diff --git a/src/provider.c b/src/provider.c index a0473fd0..6f950da8 100644 --- a/src/provider.c +++ b/src/provider.c @@ -121,6 +121,7 @@ static void fork_child(void) if (ctx_pool.contexts[i]->status == P11PROV_INITIALIZED) { /* can't re-init in the fork handler, mark it */ ctx_pool.contexts[i]->status = P11PROV_NEEDS_REINIT; + p11prov_module_mark_reinit(ctx_pool.contexts[i]->module); p11prov_slot_fork_reset(ctx_pool.contexts[i]->slots); } }