aboutsummaryrefslogtreecommitdiff
path: root/cmd/fscrypt/commands.go
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-12-15 19:31:39 -0800
committerEric Biggers <ebiggers@google.com>2020-01-05 10:02:13 -0800
commit42e0dfe85ec7a75a2fa30c417d57eae60b5a881d (patch)
treeffa9fb08a5bbe51ec23bf219ef206ddc81799453 /cmd/fscrypt/commands.go
parent2b25de6d445faefc28629603dd754aec9f744e60 (diff)
Keyring support for v2 encryption policies
Implement adding/removing v2 encryption policy keys to/from the kernel. The kernel requires that the new ioctls FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY be used for this. Root is not required. However, non-root support brings an extra complication: the kernel keeps track of which users have called FS_IOC_ADD_ENCRYPTION_KEY for the same key. FS_IOC_REMOVE_ENCRYPTION_KEY only works as one of these users, and it only removes the calling user's claim to the key; the key is only truly removed when the last claim is removed. Implement the following behavior: - 'fscrypt unlock' and pam_fscrypt add the key for the user, even if other user(s) have it added already. This behavior is needed so that another user can't remove the key out from under the user. - 'fscrypt lock' and pam_fscrypt remove the key for the user. However, if the key wasn't truly removed because other users still have it added, 'fscrypt lock' prints a warning. - 'fscrypt status' shows whether the directory is unlocked for anyone.
Diffstat (limited to 'cmd/fscrypt/commands.go')
-rw-r--r--cmd/fscrypt/commands.go35
1 files changed, 29 insertions, 6 deletions
diff --git a/cmd/fscrypt/commands.go b/cmd/fscrypt/commands.go
index 621651e..0bf0a4c 100644
--- a/cmd/fscrypt/commands.go
+++ b/cmd/fscrypt/commands.go
@@ -139,6 +139,18 @@ func encryptAction(c *cli.Context) error {
// of the key for the given encryption policy (if policy != nil) or for the
// current default encryption policy (if policy == nil).
func validateKeyringPrereqs(ctx *actions.Context, policy *actions.Policy) error {
+ var policyVersion int64
+ if policy == nil {
+ policyVersion = ctx.Config.Options.PolicyVersion
+ } else {
+ policyVersion = policy.Version()
+ }
+ // If it's a v2 policy, we're good to go, since non-root users can
+ // add/remove v2 policy keys directly to/from the filesystem, where they
+ // are usable by the filesystem on behalf of any process.
+ if policyVersion != 1 {
+ return nil
+ }
if ctx.Config.GetUseFsKeyringForV1Policies() {
// We'll be using the filesystem keyring, but it's a v1
// encryption policy so root is required.
@@ -225,14 +237,19 @@ func encryptPath(path string) (err error) {
}
}()
- // Unlock() first, so if the Unlock() fails the directory isn't changed.
- if !skipUnlockFlag.Value {
+ // Unlock() and Provision() first, so if that if these fail the
+ // directory isn't changed, and also because v2 policies can't be
+ // applied while deprovisioned unless the process is running as root.
+ if !skipUnlockFlag.Value || !policy.CanBeAppliedWithoutProvisioning() {
if err = policy.Unlock(optionFn, existingKeyFn); err != nil {
return
}
if err = policy.Provision(); err != nil {
return
}
+ if skipUnlockFlag.Value {
+ defer policy.Deprovision()
+ }
}
if err = policy.Apply(path); os.IsPermission(errors.Cause(err)) {
// EACCES at this point indicates ownership issues.
@@ -352,8 +369,9 @@ func unlockAction(c *cli.Context) error {
return newExitError(c, err)
}
// Check if directory is already unlocked
- if policy.IsProvisioned() {
- log.Printf("policy %s is already provisioned", policy.Descriptor())
+ if policy.IsProvisionedByTargetUser() {
+ log.Printf("policy %s is already provisioned by %v",
+ policy.Descriptor(), ctx.TargetUser.Username)
return newExitError(c, errors.Wrapf(ErrPolicyUnlocked, path))
}
@@ -395,8 +413,13 @@ var Lock = cli.Command{
For this to be effective, all files in the directory must first
be closed.
- The %s=true option may be needed to properly lock the directory.
- Root is required for this.
+ If the directory uses a v1 encryption policy, then the %s=true
+ option may be needed to properly lock it. Root is required for
+ this.
+
+ If the directory uses a v2 encryption policy, then a non-root
+ user can lock it, but only if it's the same user who unlocked it
+ originally and if no other users have unlocked it too.
WARNING: even after the key has been removed, decrypted data may
still be present in freed memory, where it may still be