Print this page
4912 soft_giant_mutex in pkcs11_softtoken stays held after fork

*** 19,28 **** --- 19,30 ---- * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. */ #include <strings.h> #include <errno.h> #include <cryptoutil.h>
*** 126,141 **** --- 128,149 ---- obj_to_be_freed_list_t obj_delay_freed; ses_to_be_freed_list_t ses_delay_freed; /* protects softtoken_initialized and access to C_Initialize/C_Finalize */ pthread_mutex_t soft_giant_mutex = PTHREAD_MUTEX_INITIALIZER; + /* + * ONLY SET TO TRUE BY softtoken_fork_prepare(). + * ONLY SET TO FALSE BY softtoken_fork_after(). + */ + boolean_t fork_prepared = B_FALSE; static CK_RV finalize_common(boolean_t force, CK_VOID_PTR pReserved); static void softtoken_init(); static void softtoken_fini(); static void softtoken_fork_prepare(); static void softtoken_fork_after(); + static void softtoken_fork_after_droplocks(void); CK_RV C_Initialize(CK_VOID_PTR pInitArgs) {
*** 409,428 **** * is done if softtoken is ever unloaded without a C_Finalize() call. */ static void softtoken_fini() { (void) pthread_mutex_lock(&soft_giant_mutex); ! /* if we're not initilized, do not attempt to finalize */ ! if (!softtoken_initialized) { ! (void) pthread_mutex_unlock(&soft_giant_mutex); ! return; } ! (void) finalize_common(B_TRUE, NULL_PTR); ! (void) pthread_mutex_unlock(&soft_giant_mutex); } CK_RV C_GetInfo(CK_INFO_PTR pInfo) --- 417,461 ---- * is done if softtoken is ever unloaded without a C_Finalize() call. */ static void softtoken_fini() { + int rc; + + rc = pthread_mutex_trylock(&soft_giant_mutex); + /* + * Check to see if it was acquired by softtoken_fork_prepare(). + */ + if (rc == EBUSY && fork_prepared) + rc = 0; + + if (rc != 0) { + /* + * I don't know WHAT just happened, but it's pretty bad. Grab + * the lock for real, even if it means deadlocking here. + */ (void) pthread_mutex_lock(&soft_giant_mutex); + } /* Else we acquired the lock and life is good. */ ! /* Only finalize if we're initialized. */ ! if (softtoken_initialized) { ! /* ! * We also have to DROP all of the other locks that ! * softtoken_fork_prepare did IF it was prepared, because ! * finalize_common() is going to pick them right back up. ! */ ! if (fork_prepared) ! softtoken_fork_after_droplocks(); ! (void) finalize_common(B_TRUE, NULL_PTR); ! /* ASSERT(!softtoken_initialized); */ } ! /* ! * If we don't want to drop the lock, we assume softtoken_fork_after() ! * will get called. ! */ ! if (!fork_prepared) (void) pthread_mutex_unlock(&soft_giant_mutex); } CK_RV C_GetInfo(CK_INFO_PTR pInfo)
*** 494,504 **** * 6. all soft_session_list mutexes via soft_acquire_all_session_mutexes() * 7. obj_delay_freed.obj_to_be_free_mutex; * 8. ses_delay_freed.ses_to_be_free_mutex */ void ! softtoken_fork_prepare() { (void) pthread_mutex_lock(&soft_giant_mutex); if (softtoken_initialized) { (void) pthread_mutex_lock(&soft_sessionlist_mutex); (void) pthread_mutex_lock(&soft_slot.slot_mutex); --- 527,537 ---- * 6. all soft_session_list mutexes via soft_acquire_all_session_mutexes() * 7. obj_delay_freed.obj_to_be_free_mutex; * 8. ses_delay_freed.ses_to_be_free_mutex */ void ! softtoken_fork_prepare(void) { (void) pthread_mutex_lock(&soft_giant_mutex); if (softtoken_initialized) { (void) pthread_mutex_lock(&soft_sessionlist_mutex); (void) pthread_mutex_lock(&soft_slot.slot_mutex);
*** 508,534 **** (void) pthread_mutex_lock( &obj_delay_freed.obj_to_be_free_mutex); (void) pthread_mutex_lock( &ses_delay_freed.ses_to_be_free_mutex); } } ! /* ! * Release in opposite order to softtoken_fork_prepare(). ! * Function is used for parent and child. ! */ ! void ! softtoken_fork_after() { ! if (softtoken_initialized) { ! (void) pthread_mutex_unlock( ! &ses_delay_freed.ses_to_be_free_mutex); ! (void) pthread_mutex_unlock( ! &obj_delay_freed.obj_to_be_free_mutex); soft_release_all_session_mutexes(soft_session_list); soft_release_all_session_mutexes(&token_session); (void) pthread_mutex_unlock(&soft_slot.keystore_mutex); (void) pthread_mutex_unlock(&soft_slot.slot_mutex); (void) pthread_mutex_unlock(&soft_sessionlist_mutex); ! } (void) pthread_mutex_unlock(&soft_giant_mutex); } --- 541,573 ---- (void) pthread_mutex_lock( &obj_delay_freed.obj_to_be_free_mutex); (void) pthread_mutex_lock( &ses_delay_freed.ses_to_be_free_mutex); } + fork_prepared = B_TRUE; } ! static void ! softtoken_fork_after_droplocks(void) { ! /* ASSERT(softtoken_initialized); */ ! (void) pthread_mutex_unlock(&ses_delay_freed.ses_to_be_free_mutex); ! (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex); soft_release_all_session_mutexes(soft_session_list); soft_release_all_session_mutexes(&token_session); (void) pthread_mutex_unlock(&soft_slot.keystore_mutex); (void) pthread_mutex_unlock(&soft_slot.slot_mutex); (void) pthread_mutex_unlock(&soft_sessionlist_mutex); ! } ! ! /* ! * Release in opposite order to softtoken_fork_prepare(). ! * Function is used for parent and child. ! */ ! void ! softtoken_fork_after(void) ! { ! if (softtoken_initialized) ! softtoken_fork_after_droplocks(); ! fork_prepared = B_FALSE; (void) pthread_mutex_unlock(&soft_giant_mutex); }