summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/crypto
diff options
context:
space:
mode:
authorKrishna Yenduri <Bhargava.Yenduri@Sun.COM>2009-07-23 11:15:46 -0700
committerKrishna Yenduri <Bhargava.Yenduri@Sun.COM>2009-07-23 11:15:46 -0700
commit7623016fd42aadb1a19e2c2810fe6142c795c73b (patch)
tree9630b36637034c019227968f6e43a635346163b5 /usr/src/uts/common/crypto
parentfc960aa7d5b64fecfb1cd068106eb0dc81cf5bf0 (diff)
downloadillumos-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.c23
-rw-r--r--usr/src/uts/common/crypto/core/kcf_sched.c2
-rw-r--r--usr/src/uts/common/crypto/spi/kcf_spi.c10
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);
}