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 */
|
/* init the search key mapping */
|
||||||
search_km.km_dsobj = dsobj;
|
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);
|
rw_enter(&spa->spa_keystore.sk_km_lock, RW_READER);
|
||||||
|
|
||||||
/* remove the mapping from the tree */
|
/* 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);
|
zfs_refcount_add(&found_km->km_key->dck_holds, tag);
|
||||||
|
|
||||||
rw_exit(&spa->spa_keystore.sk_km_lock);
|
rw_exit(&spa->spa_keystore.sk_km_lock);
|
||||||
|
rw_exit(&spa->spa_keystore.sk_dk_lock);
|
||||||
|
|
||||||
if (dck_out != NULL)
|
if (dck_out != NULL)
|
||||||
*dck_out = found_km->km_key;
|
*dck_out = found_km->km_key;
|
||||||
|
@ -1116,6 +1118,7 @@ spa_keystore_lookup_key(spa_t *spa, uint64_t dsobj, void *tag,
|
||||||
|
|
||||||
error_unlock:
|
error_unlock:
|
||||||
rw_exit(&spa->spa_keystore.sk_km_lock);
|
rw_exit(&spa->spa_keystore.sk_km_lock);
|
||||||
|
rw_exit(&spa->spa_keystore.sk_dk_lock);
|
||||||
|
|
||||||
if (dck_out != NULL)
|
if (dck_out != NULL)
|
||||||
*dck_out = NULL;
|
*dck_out = NULL;
|
||||||
|
|
Loading…
Reference in New Issue