diff options
author | Krishna Yenduri <Bhargava.Yenduri@Sun.COM> | 2009-07-23 11:15:46 -0700 |
---|---|---|
committer | Krishna Yenduri <Bhargava.Yenduri@Sun.COM> | 2009-07-23 11:15:46 -0700 |
commit | 7623016fd42aadb1a19e2c2810fe6142c795c73b (patch) | |
tree | 9630b36637034c019227968f6e43a635346163b5 /usr/src/uts/common/crypto | |
parent | fc960aa7d5b64fecfb1cd068106eb0dc81cf5bf0 (diff) | |
download | illumos-joyent-7623016fd42aadb1a19e2c2810fe6142c795c73b.tar.gz |
6861521 panic in kcf when calling kcf_free_provider_desc
Diffstat (limited to 'usr/src/uts/common/crypto')
-rw-r--r-- | usr/src/uts/common/crypto/core/kcf_prov_tabs.c | 23 | ||||
-rw-r--r-- | usr/src/uts/common/crypto/core/kcf_sched.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/crypto/spi/kcf_spi.c | 10 |
3 files changed, 23 insertions, 12 deletions
diff --git a/usr/src/uts/common/crypto/core/kcf_prov_tabs.c b/usr/src/uts/common/crypto/core/kcf_prov_tabs.c index d6a7be9b8d..853af88688 100644 --- a/usr/src/uts/common/crypto/core/kcf_prov_tabs.c +++ b/usr/src/uts/common/crypto/core/kcf_prov_tabs.c @@ -69,6 +69,7 @@ kmutex_t prov_tab_mutex; /* ensure exclusive access to the table */ static uint_t prov_tab_num = 0; /* number of providers in table */ static uint_t prov_tab_max = KCF_MAX_PROVIDERS; +static void kcf_free_unregistered_provs(); #if DEBUG extern int kcf_frmwrk_debug; static void kcf_prov_tab_dump(char *message); @@ -106,6 +107,10 @@ kcf_prov_tab_add_provider(kcf_provider_desc_t *prov_desc) mutex_enter(&prov_tab_mutex); + /* see if any slots can be freed */ + if (kcf_need_provtab_walk) + kcf_free_unregistered_provs(); + /* find free slot in providers table */ for (i = 0; i < KCF_MAX_PROVIDERS && prov_tab[i] != NULL; i++) ; @@ -165,6 +170,9 @@ kcf_prov_tab_rem_provider(crypto_provider_id_t prov_id) mutex_exit(&prov_tab_mutex); return (CRYPTO_INVALID_PROVIDER_ID); } + + if (kcf_need_provtab_walk) + kcf_free_unregistered_provs(); mutex_exit(&prov_tab_mutex); /* @@ -370,7 +378,9 @@ kcf_alloc_provider_desc(crypto_provider_info_t *info) } /* - * Free a provider descriptor. + * Free a provider descriptor. Caller must hold prov_tab_mutex. + * + * Caution: This routine drops prov_tab_mutex. */ void kcf_free_provider_desc(kcf_provider_desc_t *desc) @@ -378,7 +388,7 @@ kcf_free_provider_desc(kcf_provider_desc_t *desc) if (desc == NULL) return; - mutex_enter(&prov_tab_mutex); + ASSERT(MUTEX_HELD(&prov_tab_mutex)); if (desc->pd_prov_id != KCF_PROVID_INVALID) { /* release the associated providers table entry */ ASSERT(prov_tab[desc->pd_prov_id] != NULL); @@ -897,21 +907,23 @@ verify_unverified_providers() /* protected by prov_tab_mutex */ boolean_t kcf_need_provtab_walk = B_FALSE; -void +/* Caller must hold prov_tab_mutex */ +static void kcf_free_unregistered_provs() { int i; kcf_provider_desc_t *pd; boolean_t walk_again = B_FALSE; - mutex_enter(&prov_tab_mutex); + ASSERT(MUTEX_HELD(&prov_tab_mutex)); for (i = 0; i < KCF_MAX_PROVIDERS; i++) { if ((pd = prov_tab[i]) == NULL || + pd->pd_prov_type == CRYPTO_SW_PROVIDER || pd->pd_state != KCF_PROV_UNREGISTERED) continue; if (kcf_get_refcnt(pd, B_TRUE) == 0) { - mutex_exit(&prov_tab_mutex); + /* kcf_free_provider_desc drops prov_tab_mutex */ kcf_free_provider_desc(pd); mutex_enter(&prov_tab_mutex); } else @@ -919,5 +931,4 @@ kcf_free_unregistered_provs() } kcf_need_provtab_walk = walk_again; - mutex_exit(&prov_tab_mutex); } diff --git a/usr/src/uts/common/crypto/core/kcf_sched.c b/usr/src/uts/common/crypto/core/kcf_sched.c index b11cffc215..7b1d6b60fb 100644 --- a/usr/src/uts/common/crypto/core/kcf_sched.c +++ b/usr/src/uts/common/crypto/core/kcf_sched.c @@ -1504,8 +1504,6 @@ kcf_svc_wait(int *nthrs) case -1: /* Timed out. Recalculate the min/max threads */ compute_min_max_threads(); - if (kcf_need_provtab_walk) - kcf_free_unregistered_provs(); break; default: diff --git a/usr/src/uts/common/crypto/spi/kcf_spi.c b/usr/src/uts/common/crypto/spi/kcf_spi.c index 90e4dd6a0c..e502cfe926 100644 --- a/usr/src/uts/common/crypto/spi/kcf_spi.c +++ b/usr/src/uts/common/crypto/spi/kcf_spi.c @@ -475,21 +475,23 @@ crypto_unregister_provider(crypto_kcf_provider_handle_t handle) kcf_do_notify(desc, B_FALSE); + mutex_enter(&prov_tab_mutex); /* Release reference held by kcf_prov_tab_lookup(). */ KCF_PROV_REFRELE(desc); if (kcf_get_refcnt(desc, B_TRUE) == 0) { + /* kcf_free_provider_desc drops prov_tab_mutex */ kcf_free_provider_desc(desc); } else { ASSERT(desc->pd_prov_type != CRYPTO_SW_PROVIDER); /* * We could avoid this if /dev/crypto can proactively * remove any holds on us from a dormant PKCS #11 app. - * For now, a kcfd thread does a periodic check of the - * provider table for KCF_PROV_UNREGISTERED entries - * and frees them when refcnt reaches zero. + * For now, we check the provider table for + * KCF_PROV_UNREGISTERED entries when a provider is + * added to the table or when a provider is removed from it + * and free them when refcnt reaches zero. */ - mutex_enter(&prov_tab_mutex); kcf_need_provtab_walk = B_TRUE; mutex_exit(&prov_tab_mutex); } |