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

Automatically enable policy_version 2 when kernel support is detected #205

Merged
merged 6 commits into from
Mar 23, 2020
Merged

Automatically enable policy_version 2 when kernel support is detected #205

merged 6 commits into from
Mar 23, 2020

Conversation

ebiggers
Copy link
Collaborator

  • 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

@ebiggers ebiggers requested a review from josephlr March 18, 2020 21:06
@ebiggers
Copy link
Collaborator Author

@josephlr, just checking --- do you still agree with the overall approach here (making fscrypt setup set "policy_version": "2" in /etc/fscrypt.conf if it's running on kernel v5.4 or later)? This ended up being easier than the "auto" I suggested earlier, so I think we should just do this for now.

@josephlr
Copy link
Member

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.

Copy link
Member

@josephlr josephlr left a 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.

actions/policy.go Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
keyring/keyring.go Outdated Show resolved Hide resolved
Comment on lines +53 to +61
// 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) {
Copy link
Member

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.

Copy link
Collaborator Author

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.

Copy link
Member

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.
@josephlr josephlr merged commit ab531ee into google:master Mar 23, 2020
@ebiggers ebiggers deleted the autoselect-v2 branch March 23, 2020 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants