Fix 'zfs change-key' with unencrypted child

Currently, when you call 'zfs change-key' on an encrypted dataset
that has an unencrypted child, the code will trigger a VERIFY.
This VERIFY is leftover from before we allowed unencrypted
datasets to exist underneath encrypted ones. This patch fixes the
issue by simply replacing the VERIFY with an early return when
recursing through datasets.

Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Igor Kozhukhov <igor@dilos.org>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #9524
This commit is contained in:
Tom Caputi 2019-10-30 14:27:28 -04:00 committed by Brian Behlendorf
parent d46f0deb03
commit bae11ba8dc
2 changed files with 18 additions and 9 deletions

View File

@ -1430,6 +1430,7 @@ spa_keystore_change_key_sync_impl(uint64_t rddobj, uint64_t ddobj,
uint64_t new_rddobj, dsl_wrapping_key_t *wkey, boolean_t skip, uint64_t new_rddobj, dsl_wrapping_key_t *wkey, boolean_t skip,
dmu_tx_t *tx) dmu_tx_t *tx)
{ {
int ret;
zap_cursor_t *zc; zap_cursor_t *zc;
zap_attribute_t *za; zap_attribute_t *za;
dsl_pool_t *dp = dmu_tx_pool(tx); dsl_pool_t *dp = dmu_tx_pool(tx);
@ -1448,12 +1449,15 @@ spa_keystore_change_key_sync_impl(uint64_t rddobj, uint64_t ddobj,
return; return;
} }
ret = dsl_dir_get_encryption_root_ddobj(dd, &curr_rddobj);
VERIFY(ret == 0 || ret == ENOENT);
/* /*
* Stop recursing if this dsl dir didn't inherit from the root * Stop recursing if this dsl dir didn't inherit from the root
* or if this dd is a clone. * or if this dd is a clone.
*/ */
VERIFY0(dsl_dir_get_encryption_root_ddobj(dd, &curr_rddobj)); if (ret == ENOENT ||
if (!skip && (curr_rddobj != rddobj || dsl_dir_is_clone(dd))) { (!skip && (curr_rddobj != rddobj || dsl_dir_is_clone(dd)))) {
dsl_dir_rele(dd, FTAG); dsl_dir_rele(dd, FTAG);
return; return;
} }

View File

@ -28,13 +28,15 @@
# STRATEGY: # STRATEGY:
# 1. Create an encrypted dataset # 1. Create an encrypted dataset
# 2. Create an encrypted child dataset # 2. Create an encrypted child dataset
# 3. Attempt to change the key without any flags # 3. Create an unencrypted child dataset
# 4. Attempt to change the key specifying keylocation # 4. Attempt to change the key without any flags
# 5. Attempt to change the key specifying keyformat # 5. Attempt to change the key specifying keylocation
# 6. Verify the new encryption root can unload and load its key # 6. Attempt to change the key specifying keyformat
# 7. Recreate the child dataset # 7. Verify the new encryption root can unload and load its key
# 8. Attempt to change the key specifying both the keylocation and keyformat # 8. Recreate the child dataset
# 9. Verify the new encryption root can unload and load its key # 9. Attempt to change the key specifying both the keylocation and keyformat
# 10. Verify the new encryption root can unload and load its key
# 11. Verify the unencrytped child is still accessible normally
# #
verify_runnable "both" verify_runnable "both"
@ -53,6 +55,7 @@ log_assert "'zfs change-key' should promote an encrypted child to an" \
log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \ log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \
"-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1" "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
log_must zfs create $TESTPOOL/$TESTFS1/child log_must zfs create $TESTPOOL/$TESTFS1/child
log_must zfs create -o encryption=off $TESTPOOL/$TESTFS1/child2
log_mustnot eval "echo $PASSPHRASE2 | zfs change-key" \ log_mustnot eval "echo $PASSPHRASE2 | zfs change-key" \
"$TESTPOOL/$TESTFS1/child" "$TESTPOOL/$TESTFS1/child"
@ -82,5 +85,7 @@ log_must key_unavailable $TESTPOOL/$TESTFS1/child
log_must eval "echo $PASSPHRASE2 | zfs load-key $TESTPOOL/$TESTFS1/child" log_must eval "echo $PASSPHRASE2 | zfs load-key $TESTPOOL/$TESTFS1/child"
log_must key_available $TESTPOOL/$TESTFS1/child log_must key_available $TESTPOOL/$TESTFS1/child
log_must zfs unmount $TESTPOOL/$TESTFS1/child2
log_must zfs mount $TESTPOOL/$TESTFS1/child2
log_pass "'zfs change-key' promotes an encrypted child to an encryption root" log_pass "'zfs change-key' promotes an encrypted child to an encryption root"