-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow block cloning across encrypted datasets. Rebase #14705 to master, added tests. #15544
Conversation
The important case to recover a file from a snapshot is working. So happy recovering files from snapshots. |
No. See analysis in #14705 (comment) . Cloning encrypted blocks is only possible if they share the same master key, which it can only be between a dataset, its snapshots, and cloned datasets created from those snapshots. The encryption root is irrelevant, as that's only the holder of the wrapping key used to unlock the master key (datasets can be moved to another encryption root). |
We cannot check against the common encryption root. Here is a test that makes this not work:
Now the datasets rpool/ENC1/ds1 and rpool/ENC1/ds2 are under the same encryption root but have different master keys. The safest way would be to compare master keys (or check if the same master key is used), the second safest to allow only snapshots and clones of the same dataset because they have to use the same key. |
Encrypted dedup already works only within clone family (same master key). How does the check for that work? |
@oromenahar @robn I have created #15545 that does the right job IMO |
0abf958
to
5521dc2
Compare
I have updated my PR with @mmatuska code. The tests are sucessfull. |
5521dc2
to
b381b36
Compare
I agree we can use spa_crypto_key_compare(). if (spa != dmu_objset_spa(osb))
return (1); to this: if (spa != dmu_objset_spa(osb))
return (SET_ERROR(EINVAL)); For debugging purposes. |
do we even need to check if the If I would change something, it would be ret = spa_keystore_lookup_key(spa, obja, FTAG, &dcka);
if (ret != 0)
return (ret); to ret = spa_keystore_lookup_key(spa, obja, FTAG, &dcka);
if (ret != 0)
return (1); Or even change it to All of this is not how the return values of for example I'm curious to receive your feedback @mmatuska . |
I am extremely nervous about getting this wrong, so I would like to see a lot of negative tests as well, for things that shouldn't work:
|
Good point for the test. Thanks for the suggestions, add it later. |
module/zfs/dsl_crypt.c
Outdated
return (ret); | ||
} | ||
|
||
ret = spa_crypto_key_compare(dcka, dckb); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This checks that the datasets have the same dsl_crypto_key
, which includes the wrapping key. I think that means two datasets with the same master key can have different dsl_crypto_key
if one of them had its encryption root changed.
We could instead compare zk_guid
which should match as long as the underlying master key is the same. I have a branch with this check, I'll clean it up and share. We should also add a test around this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6001dad switches the check to zk_guid
and also cleans up the comparison logic according to other review comments.
I'm working on test cases. So far, I have found that performing a raw send into the same pool and then changing the key of one of the datasets is a reasonable way to end up with two different datasets with different encryption roots and the same master key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Majiir I'm not sure actually. Changing the raw "master" key should be possible unless reencryption/changing the master key will be implemented. spa_crypto_key_compare
uses the dck_obj wich should be unique for every master key. This represents the ID of ZAP object. I think this should be the same for a shared master key, shouldn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh than the ZAP-ID could be different. Maybe you are right. Than spa_crypto_key_compare wouldn't return the truth, if you are right? Not sure, going to debug it in the next days. Thanks for the implementation and the commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The on-disk structure is the wrapping key, not the master key. It's possible in principle for the same master key to be stored in multiple wrapping keys. In those cases, we would expect dck_obj
to differ but the master key (and zk_guid
) to match.
In testing, I verified with the send | recv
+change-key
scenario that using spa_crypto_key_compare
does not allow block cloning, while it works using the commit I linked above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While building tests for this, I ran into a bug where ZFS crashes after send | recv
+change-key
+cp
from another encrypted dataset. Crash log is here.
I still need to get the ZFS test suite running, but for now I have a reproducer in the form of a NixOS VM test. You don't need NixOS to run it, just the Nix package manager, which can run on your (Linux) distro of choice. To run it:
nix run github:Majiir/nixpkgs/35f0c1ad00cf4d72eeb7ffcc78e2e2a1037c6a07#nixosTests.zfs-block-cloning.stable.driver
You can find the test script here.
I tried applying #15543 and it didn't fix the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Majiir do you tested if the wrapping key is different when using send | recv + something....?
If this is so I would a hint to the original crypto_compare_function used a few minutes ago.
How did you crash this? Are you waiting for the sync before doing anything? Do you think it's related to this PR? Was sick last weekend and didn't had time to test/read your nix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The crash no longer occurs on latest master
(8ad73bf at time of writing) and block cloning works between the original filesystem and the send/recv'd one. 🎉
I'm added a list the the first post which contains the missing tests and will later contains a tests wich are implemented. I'm going to update this list when adding a test or somebody suggest a test. I will push a new version of this, including an |
b381b36
to
1b0d7d8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Just fix checkstyle and few comments.
1b0d7d8
to
c8998f7
Compare
I think we covered a lot of thoughts on three different PRs while working on encrypted cross clone. I prefer if this is merged to master. I want to create an issue to collect different possible test scenarios. I will than create a PR and update the new PR with the tests from time to time. Not all of the tests named above is written by now. But I want that people can see this issue and provide ideas. I would mange this a little bit. All of this different scenarios must not be based on encrypted cross clone and wouldn't be super related to this PR. I covered some of the important scenarios with test. (hope so) Do you think we can merge this @behlendorf and @amotin ? |
tests/zfs-tests/tests/functional/block_cloning/block_cloning_cross_enc_dataset.ksh
Show resolved
Hide resolved
tests/zfs-tests/tests/functional/block_cloning/block_cloning_cross_enc_dataset.ksh
Outdated
Show resolved
Hide resolved
c8998f7
to
a51b6d9
Compare
@robn can you please check the test block-cloning kshlib? I changed it to the cross-plattform |
When two datasets share the same master encryption key, it is safe to clone encrypted blocks. Currently only snapshots and clones of a dataset share with it the same encryption key. Signed-off-by: Kay Pedersen <[email protected]> Original-patched-by: Pawel Jakub Dawidek <[email protected]>
Added a test for: - Clone from encrypted sibling to encrypted sibling with non encrypted parent - Clone from encrypted parent to inherited encrypted child - Clone from child to sibling with encrypted parent - Clone from snapshot to the original datasets - Clone from foreign snapshot to a foreign dataset Signed-off-by: Kay Pedersen <[email protected]>
- cloning from non-encrypted to encrypted datasets - cloning from encrypted to non-encrypted datasets Signed-off-by: Kay Pedersen <[email protected]>
When two datasets share the same master encryption key, it is safe to clone encrypted blocks. Currently only snapshots and clones of a dataset share with it the same encryption key. Added a test for: - Clone from encrypted sibling to encrypted sibling with non encrypted parent - Clone from encrypted parent to inherited encrypted child - Clone from child to sibling with encrypted parent - Clone from snapshot to the original datasets - Clone from foreign snapshot to a foreign dataset - Cloning from non-encrypted to encrypted datasets - Cloning from encrypted to non-encrypted datasets Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Original-patch-by: Pawel Jakub Dawidek <[email protected]> Signed-off-by: Kay Pedersen <[email protected]> Closes openzfs#15544
When two datasets share the same master encryption key, it is safe to clone encrypted blocks. Currently only snapshots and clones of a dataset share with it the same encryption key. Added a test for: - Clone from encrypted sibling to encrypted sibling with non encrypted parent - Clone from encrypted parent to inherited encrypted child - Clone from child to sibling with encrypted parent - Clone from snapshot to the original datasets - Clone from foreign snapshot to a foreign dataset - Cloning from non-encrypted to encrypted datasets - Cloning from encrypted to non-encrypted datasets Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Original-patch-by: Pawel Jakub Dawidek <[email protected]> Signed-off-by: Kay Pedersen <[email protected]> Closes openzfs#15544
When two datasets share the same master encryption key, it is safe to clone encrypted blocks. Currently only snapshots and clones of a dataset share with it the same encryption key. Added a test for: - Clone from encrypted sibling to encrypted sibling with non encrypted parent - Clone from encrypted parent to inherited encrypted child - Clone from child to sibling with encrypted parent - Clone from snapshot to the original datasets - Clone from foreign snapshot to a foreign dataset - Cloning from non-encrypted to encrypted datasets - Cloning from encrypted to non-encrypted datasets Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Original-patch-by: Pawel Jakub Dawidek <[email protected]> Signed-off-by: Kay Pedersen <[email protected]> Closes openzfs#15544
When two datasets share the same master encryption key, it is safe to clone encrypted blocks. Currently only snapshots and clones of a dataset share with it the same encryption key. Added a test for: - Clone from encrypted sibling to encrypted sibling with non encrypted parent - Clone from encrypted parent to inherited encrypted child - Clone from child to sibling with encrypted parent - Clone from snapshot to the original datasets - Clone from foreign snapshot to a foreign dataset - Cloning from non-encrypted to encrypted datasets - Cloning from encrypted to non-encrypted datasets Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Original-patch-by: Pawel Jakub Dawidek <[email protected]> Signed-off-by: Kay Pedersen <[email protected]> Closes openzfs#15544
When two datasets share the same master encryption key, it is safe to clone encrypted blocks. Currently only snapshots and clones of a dataset share with it the same encryption key. Added a test for: - Clone from encrypted sibling to encrypted sibling with non encrypted parent - Clone from encrypted parent to inherited encrypted child - Clone from child to sibling with encrypted parent - Clone from snapshot to the original datasets - Clone from foreign snapshot to a foreign dataset - Cloning from non-encrypted to encrypted datasets - Cloning from encrypted to non-encrypted datasets Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Original-patch-by: Pawel Jakub Dawidek <[email protected]> Signed-off-by: Kay Pedersen <[email protected]> Closes #15544
Block cloning is now possible between two encrypted datasets that share the same encryption root.
This is a rebase of #14705 from @pjd and new tests. Sorry don't know how to add new commits to the old PR.
Motivation and Context
Tests are important for this feature. And we can fix a lot with good tests, before handling it to any user.
Description
The tests are described in the commit message.
There is a problem, with childs and siblings. They don't share the same encryption root. Every master key contains a key, an init Vector and a hmac. I guess that the init Vector and/or hmac changes when creating a child. But wanna throw this against the full pipeline. I'm working currently on encryption and key handling, but there is not that much time for me. Until I figure this out, it's just a quick guess without any deep dive and I wanna see the pipeline results.
Missing tests
If I forgot to test something just describe the test and I'm going to add it later.
How Has This Been Tested?
By running the new test for this.
Types of changes
Checklist:
Signed-off-by
.