-
Notifications
You must be signed in to change notification settings - Fork 98
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
Automatically enable policy_version 2 when kernel support is detected #205
Conversation
ebiggers
commented
Mar 18, 2020
- Simplify choosing the key description prefix
- Create /etc/fscrypt.conf with policy_version 2 on kernel v5.4+
- Improve error message when setting v2 policy is unsupported
- Improve error message when unlocking v2 policy is unsupported
- README.md: update examples to use v2 policies
- README.md: update v2 policy-related documentation
@josephlr, just checking --- do you still agree with the overall approach here (making |
Sorry Eric, I've been out sick, just got back in today. I agree with the general approach of just setting "2" if the kernel supports V2 policies. I'll try to review this today. |
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 looks good modulo some nits and questions about detection.
// v2 encryption policies are recommended, so set policy_version 2 when | ||
// the kernel supports it. v2 policies are supported by upstream Linux | ||
// v5.4 and later. For now we simply check the kernel version. Ideally | ||
// we'd instead check whether setting a v2 policy actually works, in | ||
// order to also detect backports of the kernel patches. However, that's | ||
// hard because from this context (creating /etc/fscrypt.conf) we may | ||
// not yet have access to a filesystem that supports encryption. | ||
var policyVersion int64 | ||
if util.IsKernelVersionAtLeast(5, 4) { |
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 is clever, but would it be possible to detect this by attempting to use one of the V2 ioctls?
I realize that FS_IOC_GET_ENCRYPTION_POLICY_EX
can't distinguish between an old kernel and an FS with no encryption support (as they both return ENOTTY
), but is the same true of FS_IOC_ADD_ENCRYPTION_KEY
?
Does that return ENOTTY
or EOPNOTSUPP
on old kernels?
Also, is there kernel config for V2 policies (or a config that was added w/ V2 support). I found CONFIG_FS_ENCRYPTION
, but that's for both V1 and V2 IIRC.
If neither of the above options work, what you have is acceptable.
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.
All the fscrypt ioctls fail with ENOTTY
both on filesystem types that don't support encryption (e.g. "xfs" or "btrfs"), and on filesystem types that do support encryption ("ext4", "f2fs", and "ubifs") when the kernel is too old to know about the ioctl.
We could iterate through all mounted filesystems and hope there is one that supports encryption where we can check for the ioctl. But the presence of such a filesystem during fscrypt setup
is not guaranteed, so we'd have to fall back to checking the kernel version anyway.
Currently, v1 and v2 policies aren't configurable separately in the kernel config; there's just CONFIG_FS_ENCRYPTION=y
. Also note it's not guaranteed that userspace has a way to check the kernel config anyway, since /proc/config.gz
and /boot/config-*
are not required.
So I think we should just go with the simple version number check for now.
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.
Version number check seems like our only option then, that's too bad.
There's no real need to allow users to choose the key description prefix (a.k.a. the "service"), since on ext4 and f2fs we can just use "ext4" and "f2fs" for compatibility with all kernels both old and new, and on other filesystems we can just use "fscrypt". So, let's do that. Since this removes the point of the "--legacy" option to 'fscrypt setup' and the "compatibility" field in /etc/fscrypt.conf, remove those too. Specifically, we start ignoring the "compatibility" in existing config files and not writing it to new ones. The corresponding protobuf field number and name are reserved. We stop accepting the "--legacy" option at all, although since it was default true and there was no real reason for anyone to change it to false, probably no one will notice. If anyone does, they should just stop specifying the option. Note that this change only affects user keyrings and thus only affects v1 encryption policies, which are deprecated in favor of v2 anyway.
v2 encryption policies are now recommended, due to various security and usability advantages over v1 policies. Many people have been running into the usability problems with v1, so it's desirable to get people onto v2 without having to manually opt-in. Therefore, when 'fscrypt setup' creates /etc/fscrypt.conf, enable policy_version 2 automatically if the kernel supports it. I decided to go with this solution over the policy_version "auto" I suggested originally because this way is simpler, it can still be changed to "auto" later if desired, and "auto" might require changing how we parse the config file (since currently the config file is mapped directly to a protobuf where policy_version is an 'int' and is shared with EncryptionOptions). Resolves #182
If trying to encrypt a directory using a v2 policy fails due to the kernel lacking support for v2 policies, show a better error message. One way this can happen is if someone runs 'fscrypt setup' with a new kernel and then downgrades to an old kernel. Before: # echo -n hunter2 | fscrypt encrypt dir --source=custom_passphrase --name=foo --quiet [ERROR] fscrypt encrypt: inappropriate ioctl for device: system error: could not add key to the keyring After: # echo -n hunter2 | fscrypt encrypt dir --source=custom_passphrase --name=foo --quiet [ERROR] fscrypt encrypt: kernel is too old to support v2 encryption policies v2 encryption policies are only supported by kernel version 5.4 and later. Either use a newer kernel, or change policy_version to 1 in /etc/fscrypt.conf.
If trying to unlock a v2-encrypted directory fails because the kernel lacks support for v2 policies, show a better error message. This can happen if someone downgrades their kernel or tries to access encrypted directories on removable storage from a computer with an older kernel. Detecting this case is difficult since all we have to go with is EACCES when opening the directory. Implement a heuristic where if get EACCES, we actually have read access to the directory, and the kernel doesn't support v2 policies, we show the improved error message. Before: # fscrypt unlock dir [ERROR] fscrypt unlock: open dir: permission denied After: # fscrypt unlock dir [ERROR] fscrypt unlock: open dir: permission denied This may be caused by the directory using a v2 encryption policy and the current kernel not supporting it. If indeed the case, then this directory can only be used on kernel v5.4 and later. You can create directories accessible on older kernels by changing policy_version to 1 in /etc/fscrypt.conf.
Since on new kernels v1 encryption policies are deprecated in favor of v2, update the examples to show v2. This mostly just consists of updating the output, as the commands are essentially the same with one notable difference in 'fscrypt lock'.
- Mention that a v5.4+ kernel is recommended. - Mention that policy_version defaults to 1 when unset. - Emphasize that v2 policies are the recommended solution to the key visibility problems, and add some more information.