Acquire sk_dk_lock during spa_keystore_lookup_key
As seen in #11490, dck_holds may be incremented (acquired) after the check in dsl_crypto_key_rele, but before the completion of dsl_crypto_key_free. All other published accesses to dsl_crypto_key-> dck_holds (i.e., spa_keystore_dsl_key_hold_impl) are protected by its parent spa->sk_dk_lock. We avoid the race by also aquiring sk_dk_lock during during spa_keystore_lookup_key's critical section. Signed-off-by: Antonio Russo <aerusso@aerusso.net>
This commit is contained in:
parent
e7a06356c1
commit
95e65c9b9f
|
@ -1095,6 +1095,7 @@ spa_keystore_lookup_key(spa_t *spa, uint64_t dsobj, void *tag,
|
|||
/* init the search key mapping */
|
||||
search_km.km_dsobj = dsobj;
|
||||
|
||||
rw_enter(&spa->spa_keystore.sk_dk_lock, RW_READER);
|
||||
rw_enter(&spa->spa_keystore.sk_km_lock, RW_READER);
|
||||
|
||||
/* remove the mapping from the tree */
|
||||
|
@ -1109,6 +1110,7 @@ spa_keystore_lookup_key(spa_t *spa, uint64_t dsobj, void *tag,
|
|||
zfs_refcount_add(&found_km->km_key->dck_holds, tag);
|
||||
|
||||
rw_exit(&spa->spa_keystore.sk_km_lock);
|
||||
rw_exit(&spa->spa_keystore.sk_dk_lock);
|
||||
|
||||
if (dck_out != NULL)
|
||||
*dck_out = found_km->km_key;
|
||||
|
@ -1116,6 +1118,7 @@ spa_keystore_lookup_key(spa_t *spa, uint64_t dsobj, void *tag,
|
|||
|
||||
error_unlock:
|
||||
rw_exit(&spa->spa_keystore.sk_km_lock);
|
||||
rw_exit(&spa->spa_keystore.sk_dk_lock);
|
||||
|
||||
if (dck_out != NULL)
|
||||
*dck_out = NULL;
|
||||
|
|
Loading…
Reference in New Issue