From 9be34ec99ec7bb518ad508851b0e60c86bfbbd24 Mon Sep 17 00:00:00 2001 From: Ameer Hamza <106930537+ixhamza@users.noreply.github.com> Date: Wed, 14 Dec 2022 06:30:46 +0500 Subject: [PATCH] Allow receiver to override encryption properties in case of replication Currently, the receiver fails to override the encryption property for the plain replicated dataset with the error: "cannot receive incremental stream: encryption property 'encryption' cannot be set for incremental streams.". The problem is resolved by allowing the receiver to override the encryption property for plain replicated send. Reviewed-by: Ryan Moeller Reviewed-by: Brian Behlendorf Signed-off-by: Ameer Hamza Closes #14253 Closes #13533 --- lib/libzfs/libzfs_sendrecv.c | 12 +++++++++++- .../zfs_receive/zfs_receive_to_encrypted.ksh | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index ac1834733..c79c636e1 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -4150,6 +4150,15 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type, goto error; } + /* + * For plain replicated send, we can ignore encryption + * properties other than first stream + */ + if ((zfs_prop_encryption_key_param(prop) || prop == + ZFS_PROP_ENCRYPTION) && !newfs && recursive && !raw) { + continue; + } + /* incremental streams can only exclude encryption properties */ if ((zfs_prop_encryption_key_param(prop) || prop == ZFS_PROP_ENCRYPTION) && !newfs && @@ -4251,7 +4260,8 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type, if (cp != NULL) *cp = '\0'; - if (!raw && zfs_crypto_create(hdl, namebuf, voprops, NULL, + if (!raw && !(!newfs && recursive) && + zfs_crypto_create(hdl, namebuf, voprops, NULL, B_FALSE, wkeydata_out, wkeylen_out) != 0) { fnvlist_free(voprops); ret = zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf); diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh index 8bd9a6854..7e12d30d0 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh @@ -41,6 +41,9 @@ verify_runnable "both" function cleanup { + datasetexists $TESTPOOL/encrypted && \ + destroy_dataset $TESTPOOL/encrypted -r + snapexists $snap && destroy_dataset $snap -f snapexists $snap2 && destroy_dataset $snap2 -f @@ -97,4 +100,15 @@ log_note "Verifying ZFS will not receive to an encrypted child when the" \ "parent key is unloaded" log_mustnot eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c4" +# Verify that replication can override encryption properties +log_note "Verifying replication can override encryption properties for plain dataset" +typeset key_location="/$TESTPOOL/pkey1" +log_must eval "echo $passphrase > $key_location" +log_must eval "zfs send -R $snap2 | zfs recv -s -F -o encryption=on" \ + "-o keyformat=passphrase -o keylocation=file://$key_location" \ + "-o mountpoint=none $TESTPOOL/encrypted" +log_must test "$(get_prop 'encryption' $TESTPOOL/encrypted)" != "off" +log_must test "$(get_prop 'keyformat' $TESTPOOL/encrypted)" == "passphrase" +log_must test "$(get_prop 'keylocation' $TESTPOOL/encrypted)" == "file://$key_location" + log_pass "ZFS can receive encrypted filesystems into child dataset"