Actions
Bug #11880
closedchanging encryption key on dataset with unencrypted children triggers VERIFY
Start date:
Due date:
% Done:
100%
Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:
Description
Doing something similar to the following:
# zfs create -o encryption=on -o keylocation=prompt -o keyformat=passphrase pool/encrypted ... # zfs create -o encryption=off pool/encrypted/unencrypted # zfs change-key pool/encrypted
Will trigger a panic similar to:
assertion failed: dsl_dir_get_encryption_root_ddobj(dd, &curr_rddobj) == 0 (0x2 == 0x0), file: ../../common/fs/zfs/dsl_crypt.c, line: 1421
0x2
is ENOENT
which makes sense -- an unencrypted dataset would not have an encrypted root. The panic stack shows the following top few frames:
> ::stack vpanic() 0xfffffffffbe35131() spa_keystore_change_key_sync_impl+0x232(20, 280, 20, fffffe8b7159ee00, fffffe8b735a8400) spa_keystore_change_key_sync_impl+0x1fd(20, 20, 20, fffffe8b7159ee00, fffffe8b735a8400) spa_keystore_change_key_sync+0x16f(fffffe00bae6c528, fffffe8b735a8400) zcp_sync_task+0x83(fffffe8672cf4e08, fffffffff7e51f30, fffffffff7e52560, fffffe00bae6c528, 1, fffffe8af9ae1620)
What appears to be happening is that spa_keystore_change_key_sync
does the following:
/* Recurse into all child dsl dirs. */ for (zap_cursor_init(zc, dp->dp_meta_objset, dsl_dir_phys(dd)->dd_child_dir_zapobj); zap_cursor_retrieve(zc, za) == 0; zap_cursor_advance(zc)) { spa_keystore_change_key_sync_impl(rddobj, za->za_first_integer, new_rddobj, wkey, tx); }
and when it calls spa_keystore_change_key_sync_impl
on an unencrypted child, the recursive call will trigger the VERIFY0.
The likely fix is to add ENOENT
as another condition to stop the recursion.
Actions