diff options
| author | Eric Biggers <ebiggers@google.com> | 2021-12-19 22:17:20 -0600 |
|---|---|---|
| committer | Eric Biggers <ebiggers@google.com> | 2021-12-20 10:24:15 -0600 |
| commit | d0b9e2c995beb13c70a1549923df482ff773f09b (patch) | |
| tree | b8d89c0ee0a18aa38b0a5df1d06ab6037f8c2190 /filesystem | |
| parent | 1014b61a6a054b5c82b2be82e13d8ce28befba45 (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')
| -rw-r--r-- | filesystem/filesystem.go | 49 | ||||
| -rw-r--r-- | filesystem/filesystem_test.go | 2 |
2 files changed, 48 insertions, 3 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 { diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index 9b534bd..92726b2 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -324,7 +324,7 @@ func getTwoSetupMounts(t *testing.T) (realMnt, fakeMnt *Mount, err error) { if err = os.MkdirAll(fakeMountpoint, basePermissions); err != nil { return } - fakeMnt = &Mount{Path: fakeMountpoint} + fakeMnt = &Mount{Path: fakeMountpoint, FilesystemType: realMnt.FilesystemType} err = fakeMnt.Setup() return } |