aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--README.md9
-rw-r--r--pam_fscrypt/config2
-rw-r--r--pam_fscrypt/pam_fscrypt.go42
3 files changed, 33 insertions, 20 deletions
diff --git a/README.md b/README.md
index 73153ed..4a59535 100644
--- a/README.md
+++ b/README.md
@@ -415,15 +415,12 @@ auth optional pam_fscrypt.so
after `pam_unix.so` in `/etc/pam.d/common-auth` or similar, and to add the
line:
```
-session optional pam_fscrypt.so drop_caches lock_policies
+session optional pam_fscrypt.so lock_policies
```
after `pam_unix.so` in `/etc/pam.d/common-session` or similar. The
`lock_policies` option locks the directories protected with the user's login
-passphrase when the last session ends. The `drop_caches` option tells `fscrypt`
-to clear the filesystem caches when the last session closes, ensuring all the
-locked data is inaccessible; this only needed for v1 encryption policies. All
-the types also support the `debug` option which prints additional debug
-information to the syslog.
+passphrase when the last session ends. All the types also support the `debug`
+option which prints additional debug information to the syslog.
### Allowing `fscrypt` to check your login passphrase
diff --git a/pam_fscrypt/config b/pam_fscrypt/config
index 9b2eb8f..d2fbf68 100644
--- a/pam_fscrypt/config
+++ b/pam_fscrypt/config
@@ -7,7 +7,7 @@ Auth-Final:
Session-Type: Additional
Session-Interactive-Only: yes
Session-Final:
- optional PAM_INSTALL_PATH drop_caches lock_policies
+ optional PAM_INSTALL_PATH lock_policies
Password-Type: Additional
Password-Final:
optional PAM_INSTALL_PATH
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.