Skip to content
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

Better handling for future crypto parameters #14577

Merged
merged 4 commits into from
Mar 7, 2023

Conversation

robn
Copy link
Member

@robn robn commented Mar 5, 2023

Motivation and Context

While testing #14249, I found a couple of places where OpenZFS doesn't cope well when presented with a dataset or stream that uses an unknown crypto suite. While its too late for those already deployed, we can at least make it that newer ZFS installs are able to fail gracefully rather than crash or do something weird.

Description

This introduces a new ioctl return, ZFS_ERR_CRYPTO_NOTSUP, and returns it when either we try to load an encryption key for a dataset that uses an unknown crypto suite (encryption property value) or receive a raw backup stream that uses an unknown encryption key. zfs send and zfs load-key have been updated to produce a nicer error message in those cases.

This is technically a very small ABI change, in that the ZFS_IOC_RECV_NEW and ZFS_IOC_LOAD_KEY can return a previously-unseen error code. Older versions of the ZFS-provided tools will handle these fine in their fallback error handlers, and I can't imagine any other users of those ioctls not having a similar fallback. If it was a problem, EINVAL or ENOTSUP are both plausible alternatives though they do muddy the meaning of those a little.

How Has This Been Tested?

Tested by hand by creating a dataset with -o encryption=chacha20-poly1305 (#14249) and a backup stream from it, and then loading it / receiving it into a ZFS build at master (620a977) and with this PR.

Before:

root@fitlet:~# zfs load-key sandisk
Key load error: Incorrect key provided for 'sandisk'.

root@fitlet:~# zfs recv -v sandisk/recv@snap < snap-from-chapoly.zfs
cannot receive new filesystem stream: invalid backup stream

root@fitlet:~# zdb -K $(cat /tmp/zfskey) -O sandisk foo
crypt < ZIO_CRYPT_FUNCTIONS (0x9 < 0x9)
ASSERT at module/os/linux/zfs/zio_crypt.c:568:zio_crypt_key_unwrap()
Aborted

Before (with --enable-debug):

root@fitlet:~# zfs load-key sandisk

Message from syslogd@fitlet at Mar  4 20:25:08 ...
 kernel:[1281777.454629] VERIFY3(crypt < ZIO_CRYPT_FUNCTIONS) failed (9 < 9)

Message from syslogd@fitlet at Mar  4 20:25:08 ...
 kernel:[1281777.454642] PANIC at zio_crypt.c:568:zio_crypt_key_unwrap()

After:

root@fitlet:~# zfs load-key sandisk
Key load error: 'sandisk' uses an unsupported encryption suite.

root@fitlet:~# zfs recv sandisk/recv@snap < snap-from-chapoly.zfs 
cannot receive new filesystem stream: stream uses crypto parameters not compatible with this pool

root@fitlet:~# zdb -K $(cat /tmp/zfskey) -O sandisk foo
zdb: couldn't load encryption key for sandisk: crypto params not supported

No additions to the test suite. I'm not really sure how to do this other than either checking in or cooking a dataset or backup stream under the hood, and that seems like it could be pretty brittle.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

robn added 4 commits March 5, 2023 17:07
The intent is that this is like ENOTSUP, but specifically for when
something can't be done because we have no support for the requested
crypto parameters; eg unlocking a dataset or receiving a stream
encrypted with a suite we don't support.

Its not intended to be recoverable without upgrading ZFS itself.
If the request could be made to work by enabling a feature or modifying
some other configuration item, then some other code should be used.

Signed-off-by: Rob Norris <[email protected]>
In the future we might have more crypto suites (ie new values for the
`encryption` property. Right now trying to load a key on such a future
crypto suite will look up suite parameters off the end of the crypto
table, resulting in misbehaviour and/or crashes (or, with debug enabled,
trip the assertion in `zio_crypt_key_unwrap`).

Instead, lets check the value we got from the dataset, and if we can't
handle it, abort early.

Signed-off-by: Rob Norris <[email protected]>
When receiving a raw stream encrypted with an unknown crypto suite, `zfs
recv` would report a generic `invalid backup stream` (EINVAL). While
technically correct, its not super helpful, so lets ship a more specific
error code and message.

Signed-off-by: Rob Norris <[email protected]>
Copy link
Contributor

@ryao ryao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all of these commits collectively relate to ZFS_ERR_CRYPTO_NOTSUP, I think they should be squashed into a single commit. I realize the irony of saying this, given that I have been doing plenty of small commits lately, but keeping those separate at least serves a documentation purpose. Here, the documentation that we would get from separate commits is self explanatory based on where the changes are being made, so there is no reason for these changes to be kept in separate commits.

@behlendorf behlendorf added the Status: Accepted Ready to integrate (reviewed, tested) label Mar 7, 2023
@behlendorf behlendorf merged commit b988f32 into openzfs:master Mar 7, 2023
mcmilk pushed a commit to mcmilk/zfs that referenced this pull request Mar 13, 2023
The intent is that this is like ENOTSUP, but specifically for when
something can't be done because we have no support for the requested
crypto parameters; eg unlocking a dataset or receiving a stream
encrypted with a suite we don't support.

Its not intended to be recoverable without upgrading ZFS itself.
If the request could be made to work by enabling a feature or modifying
some other configuration item, then some other code should be used.

load-key: In the future we might have more crypto suites (ie new values
for the `encryption` property. Right now trying to load a key on such
a future crypto suite will look up suite parameters off the end of the
crypto table, resulting in misbehaviour and/or crashes (or, with debug
enabled, trip the assertion in `zio_crypt_key_unwrap`).

Instead, lets check the value we got from the dataset, and if we can't
handle it, abort early.

recv: When receiving a raw stream encrypted with an unknown crypto
suite, `zfs recv` would report a generic `invalid backup stream`
(EINVAL). While technically correct, its not super helpful, so lets
ship a more specific error code and message.

Reviewed-by: Tino Reichardt <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Richard Yao <[email protected]>
Signed-off-by: Rob Norris <[email protected]>
Closes openzfs#14577
lundman pushed a commit to openzfsonwindows/openzfs that referenced this pull request Mar 16, 2023
The intent is that this is like ENOTSUP, but specifically for when
something can't be done because we have no support for the requested
crypto parameters; eg unlocking a dataset or receiving a stream
encrypted with a suite we don't support.

Its not intended to be recoverable without upgrading ZFS itself.
If the request could be made to work by enabling a feature or modifying
some other configuration item, then some other code should be used.

load-key: In the future we might have more crypto suites (ie new values
for the `encryption` property. Right now trying to load a key on such
a future crypto suite will look up suite parameters off the end of the
crypto table, resulting in misbehaviour and/or crashes (or, with debug
enabled, trip the assertion in `zio_crypt_key_unwrap`).

Instead, lets check the value we got from the dataset, and if we can't
handle it, abort early.

recv: When receiving a raw stream encrypted with an unknown crypto
suite, `zfs recv` would report a generic `invalid backup stream`
(EINVAL). While technically correct, its not super helpful, so lets
ship a more specific error code and message.

Reviewed-by: Tino Reichardt <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Richard Yao <[email protected]>
Signed-off-by: Rob Norris <[email protected]>
Closes openzfs#14577
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Accepted Ready to integrate (reviewed, tested)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants