aboutsummaryrefslogtreecommitdiff
path: root/pam_fscrypt/pam_fscrypt.go
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2021-03-08 15:20:08 -0800
committerEric Biggers <ebiggers@google.com>2021-03-08 15:20:08 -0800
commit28e4999ebd9221a71488d715d9f1182b494216d8 (patch)
treee4361f539537b9b7c37d331388db5ab908cd25e6 /pam_fscrypt/pam_fscrypt.go
parent90a96e4473ae7bcf61a97f25fc67a9a953187f56 (diff)
pam_fscrypt: decide cache dropping behavior automatically
Configuring whether pam_fscrypt drops caches or not isn't really something the user should have to do, and it's also irrelevant for v2 encryption policies (the default on newer systems). It's better to have pam_fscrypt automatically decide whether it needs to drop caches or not. Do this by making pam_fscrypt check whether any encryption policy keys are being removed from a user keyring (rather than from a filesystem keyring). If so, it drops caches; otherwise it doesn't. This supersedes the "drop_caches" option, which won't do anything anymore.
Diffstat (limited to 'pam_fscrypt/pam_fscrypt.go')
-rw-r--r--pam_fscrypt/pam_fscrypt.go42
1 files changed, 29 insertions, 13 deletions
diff --git a/pam_fscrypt/pam_fscrypt.go b/pam_fscrypt/pam_fscrypt.go
index a7582cc..195ba43 100644
--- a/pam_fscrypt/pam_fscrypt.go
+++ b/pam_fscrypt/pam_fscrypt.go
@@ -48,7 +48,12 @@ const (
// These flags are used to toggle behavior of the PAM module.
debugFlag = "debug"
lockFlag = "lock_policies"
- cacheFlag = "drop_caches"
+
+ // This option is accepted for compatibility with existing config files,
+ // but it no longer does anything. pam_fscrypt now drops caches if and
+ // only if it is needed. (Usually it is not needed anymore, as the
+ // FS_IOC_REMOVE_ENCRYPTION_KEY ioctl handles this automatically.)
+ dropCachesFlag = "drop_caches"
)
var (
@@ -213,15 +218,20 @@ func CloseSession(handle *pam.Handle, args map[string]bool) error {
return err
}
+ if args[dropCachesFlag] {
+ log.Print("ignoring deprecated 'drop_caches' option (now auto-detected)")
+ }
+
+ needDropCaches := false
var errLock, errCache error
// Don't automatically drop privileges, since we may need them to
// deprovision policies or to drop caches.
if args[lockFlag] {
log.Print("locking polices protected with login protector")
- errLock = lockLoginPolicies(handle)
+ needDropCaches, errLock = lockLoginPolicies(handle)
}
- if args[cacheFlag] {
+ if needDropCaches {
log.Print("dropping appropriate filesystem caches at session close")
errCache = security.DropFilesystemCache()
}
@@ -232,11 +242,14 @@ func CloseSession(handle *pam.Handle, args map[string]bool) error {
return errCache
}
-// lockLoginPolicies deprovisions all policy keys that are protected by
-// the user's login protector.
-func lockLoginPolicies(handle *pam.Handle) error {
+// lockLoginPolicies deprovisions all policy keys that are protected by the
+// user's login protector. It returns true if dropping filesystem caches will
+// be needed afterwards to completely lock the relevant directories.
+func lockLoginPolicies(handle *pam.Handle) (bool, error) {
+ needDropCaches := false
+
if err := handle.StartAsPamUser(); err != nil {
- return err
+ return needDropCaches, err
}
defer handle.StopAsPamUser()
@@ -244,16 +257,16 @@ func lockLoginPolicies(handle *pam.Handle) error {
protector, err := loginProtector(handle)
if err != nil {
log.Printf("nothing to lock: %s", err)
- return nil
+ return needDropCaches, nil
}
policies := policiesUsingProtector(protector)
if len(policies) == 0 {
log.Print("no policies to lock")
- return nil
+ return needDropCaches, nil
}
if err = setupUserKeyringIfNeeded(handle, policies); err != nil {
- return errors.Wrapf(err, "setting up user keyring")
+ return needDropCaches, errors.Wrapf(err, "setting up user keyring")
}
// We will try to deprovision all of the policies.
@@ -263,12 +276,15 @@ func lockLoginPolicies(handle *pam.Handle) error {
policy.Descriptor(), handle.PamUser.Username)
continue
}
+ if policy.NeedsUserKeyring() {
+ needDropCaches = true
+ }
if err := beginProvisioningOp(handle, policy); err != nil {
- return err
+ return needDropCaches, err
}
deprovisionErr := policy.Deprovision(false)
if err := endProvisioningOp(handle, policy); err != nil {
- return err
+ return needDropCaches, err
}
if deprovisionErr != nil {
log.Printf("deprovisioning policy %s: %s", policy.Descriptor(), deprovisionErr)
@@ -276,7 +292,7 @@ func lockLoginPolicies(handle *pam.Handle) error {
}
log.Printf("policy %s deprovisioned by %v", policy.Descriptor(), handle.PamUser.Username)
}
- return nil
+ return needDropCaches, nil
}
// Chauthtok rewraps the login protector when the passphrase changes.