aboutsummaryrefslogtreecommitdiff
path: root/actions
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 /actions
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 'actions')
-rw-r--r--actions/context.go4
-rw-r--r--actions/policy.go27
2 files changed, 24 insertions, 7 deletions
diff --git a/actions/context.go b/actions/context.go
index f7e98cf..f07f225 100644
--- a/actions/context.go
+++ b/actions/context.go
@@ -62,7 +62,9 @@ type Context struct {
// the filesystem keyring are provisioned.
Mount *filesystem.Mount
// TargetUser is the user for whom protectors are created, and to whose
- // keyring policies using the user keyring are provisioned.
+ // keyring policies using the user keyring are provisioned. It's also
+ // the user for whom the keys are claimed in the filesystem keyring when
+ // v2 policies are provisioned.
TargetUser *user.User
}
diff --git a/actions/policy.go b/actions/policy.go
index f6d3ea9..f448620 100644
--- a/actions/policy.go
+++ b/actions/policy.go
@@ -63,6 +63,9 @@ func PurgeAllPolicies(ctx *Context) error {
case keyring.ErrKeyFilesOpen:
log.Printf("Key for policy %s couldn't be fully removed because some files are still in-use",
policyDescriptor)
+ case keyring.ErrKeyAddedByOtherUsers:
+ log.Printf("Key for policy %s couldn't be fully removed because other user(s) have added it too",
+ policyDescriptor)
default:
return err
}
@@ -200,6 +203,11 @@ func (policy *Policy) Options() *metadata.EncryptionOptions {
return policy.data.Options
}
+// Version returns the version of this policy.
+func (policy *Policy) Version() int64 {
+ return policy.data.Options.PolicyVersion
+}
+
// Destroy removes a policy from the filesystem. The internal key should still
// be wiped with Lock().
func (policy *Policy) Destroy() error {
@@ -382,14 +390,15 @@ func (policy *Policy) GetProvisioningStatus() keyring.KeyStatus {
return status
}
-// IsProvisioned returns a boolean indicating if the policy has its key in the
-// keyring, meaning files and directories using this policy are accessible.
-func (policy *Policy) IsProvisioned() bool {
+// IsProvisionedByTargetUser returns true if the policy's key is present in the
+// target kernel keyring, but not if that keyring is a filesystem keyring and
+// the key only been added by users other than Context.TargetUser.
+func (policy *Policy) IsProvisionedByTargetUser() bool {
return policy.GetProvisioningStatus() == keyring.KeyPresent
}
// IsFullyDeprovisioned returns true if the policy has been fully deprovisioned,
-// including all files protected by it having been closed.
+// including by all users and with all files protected by it having been closed.
func (policy *Policy) IsFullyDeprovisioned() bool {
return policy.GetProvisioningStatus() == keyring.KeyAbsent
}
@@ -415,13 +424,19 @@ func (policy *Policy) Deprovision() error {
// NeedsUserKeyring returns true if Provision and Deprovision for this policy
// will use a user keyring, not a filesystem keyring.
func (policy *Policy) NeedsUserKeyring() bool {
- return !policy.Context.Config.GetUseFsKeyringForV1Policies()
+ return policy.Version() == 1 && !policy.Context.Config.GetUseFsKeyringForV1Policies()
}
// NeedsRootToProvision returns true if Provision and Deprovision will require
// root for this policy in the current configuration.
func (policy *Policy) NeedsRootToProvision() bool {
- return policy.Context.Config.GetUseFsKeyringForV1Policies()
+ return policy.Version() == 1 && policy.Context.Config.GetUseFsKeyringForV1Policies()
+}
+
+// CanBeAppliedWithoutProvisioning returns true if this process can apply this
+// policy to a directory without first calling Provision.
+func (policy *Policy) CanBeAppliedWithoutProvisioning() bool {
+ return policy.Version() == 1 || util.IsUserRoot()
}
// commitData writes the Policy's current data to the filesystem.