aboutsummaryrefslogtreecommitdiff
path: root/filesystem/filesystem.go
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2021-12-19 22:17:20 -0600
committerEric Biggers <ebiggers@google.com>2021-12-20 10:24:15 -0600
commitd0b9e2c995beb13c70a1549923df482ff773f09b (patch)
treeb8d89c0ee0a18aa38b0a5df1d06ab6037f8c2190 /filesystem/filesystem.go
parent1014b61a6a054b5c82b2be82e13d8ce28befba45 (diff)
filesystem: avoid accessing irrelevant filesystems
Forbid 'fscrypt setup' on filesystems that aren't expected to support encryption (other than the root filesystem), and skip looking for fscrypt metadata directories on such filesystems. This has two benefits. First, it avoids the printing of annoying warnings like: pam_fscrypt[75038]: stat /run/user/0/.fscrypt: permission denied pam_fscrypt[75038]: stat /run/user/0/.fscrypt/policies: permission denied pam_fscrypt[75038]: stat /run/user/0/.fscrypt/protectors: permission denied pam_fscrypt[75038]: stat /sys/firmware/efi/efivars/.fscrypt: invalid argument pam_fscrypt[75038]: stat /sys/firmware/efi/efivars/.fscrypt/policies: invalid argument pam_fscrypt[75038]: stat /sys/firmware/efi/efivars/.fscrypt/protectors: invalid argument pam_fscrypt[75038]: stat /sys/fs/pstore/.fscrypt: permission denied pam_fscrypt[75038]: stat /sys/fs/pstore/.fscrypt/policies: permission denied pam_fscrypt[75038]: stat /sys/fs/pstore/.fscrypt/protectors: permission denied Second, it avoids long delays or side effects on some filesystems. To do this, introduce an allowlist of filesystem types that fscrypt will recognize. I wanted to avoid doing this, since this list will need to be updated in the future, but I don't see a better solution.
Diffstat (limited to 'filesystem/filesystem.go')
-rw-r--r--filesystem/filesystem.go49
1 files changed, 47 insertions, 2 deletions
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 456a4fc..0b30452 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -112,6 +112,17 @@ func (err *ErrNotSetup) Error() string {
return fmt.Sprintf("filesystem %s is not setup for use with fscrypt", err.Mount.Path)
}
+// ErrSetupNotSupported indicates that the given filesystem type is not
+// supported for fscrypt setup.
+type ErrSetupNotSupported struct {
+ Mount *Mount
+}
+
+func (err *ErrSetupNotSupported) Error() string {
+ return fmt.Sprintf("filesystem type %s is not supported for fscrypt setup",
+ err.Mount.FilesystemType)
+}
+
// ErrPolicyNotFound indicates that the policy metadata was not found.
type ErrPolicyNotFound struct {
Descriptor string
@@ -299,15 +310,46 @@ func (m *Mount) EncryptionSupportError(err error) error {
return err
}
-// CheckSupport returns an error if this filesystem does not support filesystem
-// encryption.
+// isFscryptSetupAllowed decides whether the given filesystem is allowed to be
+// set up for fscrypt, without actually accessing it. This basically checks
+// whether the filesystem type is one of the types that supports encryption, or
+// at least is in some stage of planning for encrption support in the future.
+//
+// We need this list so that we can skip filesystems that are irrelevant for
+// fscrypt without having to look for the fscrypt metadata directories on them,
+// which can trigger errors, long delays, or side effects on some filesystems.
+//
+// Unfortunately, this means that if a completely new filesystem adds encryption
+// support, then it will need to be manually added to this list. But it seems
+// to be a worthwhile tradeoff to avoid the above issues.
+func (m *Mount) isFscryptSetupAllowed() bool {
+ if m.Path == "/" {
+ // The root filesystem is always allowed, since it's where login
+ // protectors are stored.
+ return true
+ }
+ switch m.FilesystemType {
+ case "ext4", "f2fs", "ubifs", "btrfs", "ceph", "xfs":
+ return true
+ default:
+ return false
+ }
+}
+
+// CheckSupport returns an error if this filesystem does not support encryption.
func (m *Mount) CheckSupport() error {
+ if !m.isFscryptSetupAllowed() {
+ return &ErrEncryptionNotSupported{m}
+ }
return m.EncryptionSupportError(metadata.CheckSupport(m.Path))
}
// CheckSetup returns an error if all the fscrypt metadata directories do not
// exist. Will log any unexpected errors or incorrect permissions.
func (m *Mount) CheckSetup() error {
+ if !m.isFscryptSetupAllowed() {
+ return &ErrNotSetup{m}
+ }
// Run all the checks so we will always get all the warnings
baseGood := isDirCheckPerm(m.BaseDir(), basePermissions)
policyGood := isDirCheckPerm(m.PolicyDir(), dirPermissions)
@@ -345,6 +387,9 @@ func (m *Mount) Setup() error {
if m.CheckSetup() == nil {
return &ErrAlreadySetup{m}
}
+ if !m.isFscryptSetupAllowed() {
+ return &ErrSetupNotSupported{m}
+ }
// We build the directories under a temp Mount and then move into place.
temp, err := m.tempMount()
if err != nil {