Skip to content

Commit

Permalink
Fix incremental recursive encrypted receive
Browse files Browse the repository at this point in the history
Currently, incremental recursive encrypted receives fail to work
for any snapshot after the first. The reason for this is because
the check in zfs_setup_cmdline_props() did not properly realize
that when the user attempts to use '-x encryption' in this
situation, they are not really overriding the existing encryption
property and instead are attempting to prevent it from changing.
This resulted in an error message stating: "encryption property
'encryption' cannot be set or excluded for raw or incremental
streams".

This problem is fixed by updating the logic to expect this use
case.

Reviewed-by: loli10K <ezomori.nozomu@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 openzfs#9494
  • Loading branch information
Tom Caputi authored and tonyhutter committed Dec 26, 2019
1 parent 917966e commit c3ffb6c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
22 changes: 17 additions & 5 deletions lib/libzfs/libzfs_sendrecv.c
Original file line number Diff line number Diff line change
Expand Up @@ -3659,11 +3659,21 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,

/* raw streams can't override encryption properties */
if ((zfs_prop_encryption_key_param(prop) ||
prop == ZFS_PROP_ENCRYPTION) && (raw || !newfs)) {
prop == ZFS_PROP_ENCRYPTION) && raw) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"encryption property '%s' cannot "
"be set or excluded for raw or incremental "
"streams."), name);
"be set or excluded for raw streams."), name);
ret = zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}

/* incremental streams can only exclude encryption properties */
if ((zfs_prop_encryption_key_param(prop) ||
prop == ZFS_PROP_ENCRYPTION) && !newfs &&
nvpair_type(nvp) != DATA_TYPE_BOOLEAN) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"encryption property '%s' cannot "
"be set for incremental streams."), name);
ret = zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}
Expand All @@ -3681,10 +3691,12 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
*/
if (nvlist_exists(origprops, name)) {
nvlist_t *attrs;
char *source = NULL;

attrs = fnvlist_lookup_nvlist(origprops, name);
if (strcmp(fnvlist_lookup_string(attrs,
ZPROP_SOURCE), ZPROP_SOURCE_VAL_RECVD) != 0)
if (nvlist_lookup_string(attrs,
ZPROP_SOURCE, &source) == 0 &&
strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0)
continue;
}
/*
Expand Down
18 changes: 17 additions & 1 deletion tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ log_assert "'zfs recv' must properly handle encryption properties"

typeset keyfile=/$TESTPOOL/pkey
typeset sendfile=/$TESTPOOL/sendfile
typeset snap=$TESTPOOL/ds@snap
typeset snap=$TESTPOOL/ds@snap1
typeset snap2=$TESTPOOL/ds@snap2
typeset esnap=$TESTPOOL/crypt@snap1
typeset esnap2=$TESTPOOL/crypt@snap2

Expand All @@ -78,6 +79,7 @@ log_must cp /$TESTPOOL/ds/$TESTFILE0 /$TESTPOOL/crypt/$TESTFILE0
typeset cksum=$(md5digest /$TESTPOOL/ds/$TESTFILE0)

log_must zfs snap -r $snap
log_must zfs snap -r $snap2
log_must zfs snap -r $esnap
log_must zfs snap -r $esnap2

Expand Down Expand Up @@ -193,6 +195,20 @@ recv_cksum=$(md5digest /$ds/$TESTFILE0)
log_must test "$recv_cksum" == "$cksum"
log_must zfs destroy -r $ds

# Test that we can override an unencrypted, incremental, recursive stream's
# encryption settings, receiving all datasets as encrypted children.
log_note "Must be able to receive recursive stream to encrypted child"
ds=$TESTPOOL/crypt/recv
log_must eval "zfs send -R $snap2 > $sendfile"
log_must eval "zfs recv -x encryption $ds < $sendfile"
log_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
log_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
log_must test "$(get_prop 'mounted' $ds)" == "yes"
recv_cksum=$(md5digest /$ds/$TESTFILE0)
log_must test "$recv_cksum" == "$cksum"
log_must zfs destroy -r $ds

# Check that we haven't printed the key to the zpool history log
log_mustnot eval "zpool history -i | grep -q 'wkeydata'"

Expand Down

0 comments on commit c3ffb6c

Please sign in to comment.