@@ -132,10 +132,16 @@ static BOOL is_keysinuse_enabled();
132132static void keysinuse_init_internal ();
133133static void keysinuse_cleanup_internal ();
134134static void keysinuse_teardown ();
135- static void keysinuse_atfork_reinit ();
135+
136+ static void keysinuse_atfork_prepare ();
137+ static void keysinuse_atfork_parent ();
138+ static void keysinuse_atfork_child ();
139+
140+ static void keysinuse_lock_key_ctx (_Inout_ SCOSSL_KEYSINUSE_CTX_IMP * ctx );
141+ static void keysinuse_unlock_key_ctx (_Inout_ SCOSSL_KEYSINUSE_CTX_IMP * ctx );
136142
137143static void keysinuse_free_key_ctx (_Inout_ SCOSSL_KEYSINUSE_CTX_IMP * ctx );
138- static void keysinuse_reset_key_ctx (_Inout_ SCOSSL_KEYSINUSE_CTX_IMP * ctx );
144+ static void keysinuse_atfork_reset_key_ctx (_Inout_ SCOSSL_KEYSINUSE_CTX_IMP * ctx );
139145static void keysinuse_ctx_log (_Inout_ SCOSSL_KEYSINUSE_CTX_IMP * ctx , _In_ PVOID doallArg );
140146
141147static void keysinuse_log_common (int level , _In_ const char * message , va_list args );
@@ -280,7 +286,9 @@ static void keysinuse_init_internal()
280286 goto cleanup ;
281287 }
282288
283- if ((pthreadErr = pthread_atfork (NULL , NULL , keysinuse_atfork_reinit )) != 0 )
289+ if ((pthreadErr = pthread_atfork (keysinuse_atfork_prepare ,
290+ keysinuse_atfork_parent ,
291+ keysinuse_atfork_child )) != 0 )
284292 {
285293 keysinuse_log_error ("Failed to register logging fork handler,SYS_%d" , pthreadErr );
286294 goto cleanup ;
@@ -339,63 +347,68 @@ void keysinuse_init()
339347 CRYPTO_THREAD_run_once (& keysinuse_init_once , keysinuse_init_internal );
340348}
341349
342- // If the calling process forks, the logging thread needs to be restarted in the
343- // child process, and any locks should be reinitialized in case the parent
344- // process held a lock at the time of the fork.
345- static void keysinuse_atfork_reinit ()
350+
351+ // acquire all locks to freeze state before fork
352+ static void keysinuse_atfork_prepare ()
353+ {
354+ pthread_mutex_lock (& logging_thread_mutex );
355+
356+ if (lh_keysinuse_ctx_imp_lock != NULL )
357+ {
358+ CRYPTO_THREAD_write_lock (lh_keysinuse_ctx_imp_lock );
359+ }
360+
361+ if (lh_keysinuse_ctx_imp != NULL )
362+ {
363+ lh_SCOSSL_KEYSINUSE_CTX_IMP_doall (lh_keysinuse_ctx_imp , keysinuse_lock_key_ctx );
364+ }
365+ }
366+
367+ // release all locks in reverse order after fork
368+ static void keysinuse_atfork_parent ()
369+ {
370+ if (lh_keysinuse_ctx_imp != NULL )
371+ {
372+ lh_SCOSSL_KEYSINUSE_CTX_IMP_doall (lh_keysinuse_ctx_imp , keysinuse_unlock_key_ctx );
373+ }
374+
375+ if (lh_keysinuse_ctx_imp_lock != NULL )
376+ {
377+ CRYPTO_THREAD_unlock (lh_keysinuse_ctx_imp_lock );
378+ }
379+
380+ pthread_mutex_unlock (& logging_thread_mutex );
381+ }
382+
383+ // The logging thread needs to be restarted in the child process.
384+ // Inherited locks are destroyed and recreated to ensure they are in a clean, unlocked state.
385+ static void keysinuse_atfork_child ()
346386{
347387 pthread_condattr_t attr ;
348388 int pthreadErr ;
349389 SCOSSL_STATUS status = SCOSSL_FAILURE ;
350390 int is_parent_logging = is_logging ;
351391 int is_parent_running = keysinuse_running ;
352- unsigned long lhDownLoad = 0 ;
353392
354393 // Reset global state
355394 keysinuse_running = FALSE;
356395 first_use_pending = FALSE;
357396 is_logging = FALSE;
358397 logging_thread_exit_status = SCOSSL_FAILURE ;
359398
360- logging_thread_mutex = (pthread_mutex_t ) PTHREAD_MUTEX_INITIALIZER ;
361-
362- // Recreate global locks in case they were held by the logging
363- // thread in the parent process at the time of the fork.
364- CRYPTO_THREAD_lock_free (lh_keysinuse_ctx_imp_lock );
365- lh_keysinuse_ctx_imp_lock = CRYPTO_THREAD_lock_new ();
366- if (lh_keysinuse_ctx_imp_lock == NULL )
399+ if (lh_keysinuse_ctx_imp != NULL )
367400 {
368- keysinuse_log_error ("Failed to create keysinuse lock in child process" );
369- goto cleanup ;
401+ lh_SCOSSL_KEYSINUSE_CTX_IMP_doall (lh_keysinuse_ctx_imp , keysinuse_atfork_reset_key_ctx );
370402 }
371403
372- if (CRYPTO_THREAD_write_lock ( lh_keysinuse_ctx_imp_lock ) )
404+ if (lh_keysinuse_ctx_imp_lock != NULL )
373405 {
374- if (lh_keysinuse_ctx_imp != NULL )
375- {
376- // Set load factor to 0 during this operation to prevent hash table contraction.
377- lhDownLoad = lh_SCOSSL_KEYSINUSE_CTX_IMP_get_down_load (lh_keysinuse_ctx_imp );
378- lh_SCOSSL_KEYSINUSE_CTX_IMP_set_down_load (lh_keysinuse_ctx_imp , 0 );
379-
380- lh_SCOSSL_KEYSINUSE_CTX_IMP_doall (lh_keysinuse_ctx_imp , keysinuse_reset_key_ctx );
381-
382- // Restore original down_load
383- lh_SCOSSL_KEYSINUSE_CTX_IMP_set_down_load (lh_keysinuse_ctx_imp , lhDownLoad );
384- }
385-
386- CRYPTO_THREAD_unlock (lh_keysinuse_ctx_imp_lock );
387-
388- if (lh_keysinuse_ctx_imp == NULL )
389- {
390- keysinuse_log_error ("Keysinuse context hash table is missing in fork handler" );
391- goto cleanup ;
392- }
393- }
394- else
395- {
396- keysinuse_log_error ("Failed to lock keysinuse context hash table in fork handler,OPENSSL_%d" , ERR_get_error ());
406+ CRYPTO_THREAD_lock_free (lh_keysinuse_ctx_imp_lock );
407+ lh_keysinuse_ctx_imp_lock = CRYPTO_THREAD_lock_new ();
397408 }
398409
410+ pthread_mutex_unlock (& logging_thread_mutex );
411+
399412 // Only recreate logging thread if it was running in the parent process and keysinuse is enabled
400413 if (is_parent_logging && is_parent_running && is_keysinuse_enabled ())
401414 {
@@ -784,31 +797,41 @@ static void keysinuse_free_key_ctx(SCOSSL_KEYSINUSE_CTX_IMP *ctx)
784797}
785798
786799_Use_decl_annotations_
787- static void keysinuse_reset_key_ctx (SCOSSL_KEYSINUSE_CTX_IMP * ctx )
800+ static void keysinuse_lock_key_ctx (SCOSSL_KEYSINUSE_CTX_IMP * ctx )
788801{
789- if (ctx == NULL )
790- return ;
791-
792- CRYPTO_THREAD_lock_free (ctx -> lock );
793- ctx -> lock = CRYPTO_THREAD_lock_new ();
794- if (ctx -> lock == NULL )
802+ if (ctx && ctx -> lock )
795803 {
796- keysinuse_enabled = FALSE;
797- keysinuse_log_error ("Failed to create keysinuse context lock in fork handler" );
798- return ;
804+ CRYPTO_THREAD_write_lock (ctx -> lock );
799805 }
806+ }
800807
801- if (CRYPTO_THREAD_write_lock (ctx -> lock ))
808+ _Use_decl_annotations_
809+ static void keysinuse_unlock_key_ctx (SCOSSL_KEYSINUSE_CTX_IMP * ctx )
810+ {
811+ if (ctx && ctx -> lock )
802812 {
803- // Reset counters
804- ctx -> signCounter = 0 ;
805- ctx -> decryptCounter = 0 ;
813+ CRYPTO_THREAD_unlock ( ctx -> lock );
814+ }
815+ }
806816
807- // Reset timestamps
808- ctx -> firstLogTime = 0 ;
809- ctx -> lastLogTime = 0 ;
817+ _Use_decl_annotations_
818+ static void keysinuse_atfork_reset_key_ctx (SCOSSL_KEYSINUSE_CTX_IMP * ctx )
819+ {
820+ if (ctx == NULL )
821+ return ;
810822
811- CRYPTO_THREAD_unlock (ctx -> lock );
823+ // Reset counters
824+ ctx -> signCounter = 0 ;
825+ ctx -> decryptCounter = 0 ;
826+
827+ // Reset timestamps
828+ ctx -> firstLogTime = 0 ;
829+ ctx -> lastLogTime = 0 ;
830+
831+ if (ctx -> lock )
832+ {
833+ CRYPTO_THREAD_lock_free (ctx -> lock );
834+ ctx -> lock = CRYPTO_THREAD_lock_new ();
812835 }
813836}
814837
0 commit comments