aboutsummaryrefslogtreecommitdiff
path: root/filesystem/filesystem.go
AgeCommit message (Collapse)Author
2022-02-23filesystem: create metadata files with mode 0600Eric Biggers
Currently, fscrypt policies and protectors are world readable, as they are created with mode 0644. While this can be nice for use cases where users share these files, those use cases seem to be quite rare, and it's not a great default security-wise since it exposes password hashes to all users. While fscrypt uses a very strong password hash algorithm, it would still be best to follow the lead of /etc/shadow and keep this information non-world-readable. Therefore, start creating these files with mode 0600. Of course, if users do actually want to share these files, they have the option of simply chmod'ing them to a less restrictive mode. An option could also be added to make fscrypt use the old mode 0644; however, the need for that is currently unclear.
2022-02-23filesystem: preserve metadata file permissions on updatesEric Biggers
Since fscrypt replaces metadata files rather than overwrites them (to get atomicity), their owner will change to root if root makes a change. That isn't too much of an issue when the files have mode 0644. However, it will become a much bigger issue when the files have mode 0600, especially because existing files with mode 0644 would also get changed to have mode 0600. In preparation for this, start preserving the previous owner and mode of policy and protector files when they are updated.
2022-02-23Make all new metadata files owned by user when neededEric Biggers
Since commit 4c7c6631cc5a ("Set owner of login protectors to correct user"), login protectors are made owned by the user when root creates one on a user's behalf. That's good, but the same isn't true of other files that get created at the same time: - The policy protecting the directory - The protector link file, if the policy is on a different filesystem - The recovery protector, if the policy is on a different filesystem - The recovery instructions file In preparation for setting all metadata files to mode 0600, start making all these files owned by the user in this scenario as well.
2022-02-23Extend ownership validation to entire directory structureEric Biggers
A previous commit extended file ownership validation to policy and protector files (by default -- there's an opt-out in /etc/fscrypt.conf). However, that didn't apply to the parent directories: MOUNTPOINT MOUNTPOINT/.fscrypt MOUNTPOINT/.fscrypt/policies MOUNTPOINT/.fscrypt/protectors The problem is that if the parent directories aren't trusted (owned by another non-root user), then untrusted changes to their contents can be made at any time, including the introduction of symlinks and so on. While it's debatable how much of a problem this really is, given the other validations that are done, it seems to be appropriate to validate the parent directories too. Therefore, this commit applies the same ownership validations to the above four directories as are done on the metadata files themselves. In addition, it is validated that none of these directories are symlinks except for ".fscrypt" where this is explicitly supported.
2022-02-23Strictly validate metadata file ownership by defaultEric Biggers
The metadata validation checks introduced by the previous commits are good, but to reduce the attack surface it would be much better to avoid reading and parsing files owned by other users in the first place. There are some possible use cases for users sharing fscrypt metadata files, but I think that for the vast majority of users it is unneeded and just opens up attack surface. Thus, make fscrypt (and pam_fscrypt) not process policies or protectors owned by other users by default. Specifically, * If fscrypt or pam_fscrypt is running as a non-root user, only policies and protectors owned by the user or by root can be used. * If fscrypt is running as root, any policy or protector can be used. (This is to match user expectations -- starting a sudo session should gain rights, not remove rights.) * If pam_fscrypt is running as root, only policies and protectors owned by root can be used. Note that this only applies when the root user themselves has an fscrypt login protector, which is rare. Add an option 'allow_cross_user_metadata' to /etc/fscrypt.conf which allows restoring the old behavior for anyone who really needs it.
2022-02-23Make 'fscrypt setup' offer a choice of directory modesEric Biggers
World-writable directories are not appropriate for some systems, so offer a choice of single-user-writable and world-writable modes, with single-user-writable being the default. Add a new documentation section to help users decide which one to use.
2022-02-23filesystem: fall back to non-atomic overwrites when requiredEric Biggers
To allow users to update fscrypt metadata they own in single-user-writable metadata directories (introduced by the next commit), fall back to non-atomic overwrites when atomic ones can't be done due to not having write access to the directory.
2022-02-23filesystem: reject spoofed login protectorsEric Biggers
If a login protector contains a UID that differs from the file owner (and the file owner is not root), it might be a spoofed file that was created maliciously, so make sure to consider such files to be invalid.
2022-02-23filesystem: validate size and type of metadata filesEric Biggers
Don't allow reading metadata files that are very large, as they can crash the program due to the memory required. Similarly, don't allow reading metadata files that aren't regular files, such as FIFOs, or symlinks (which could point to a device node like /dev/zero), as that can hang the program. Both issues were particularly problematic for pam_fscrypt, as they could prevent users from being able to log in. Note: these checks are arguably unneeded if we strictly check the file ownership too, which a later commit will do. But there's no reason not to do these basic checks too.
2022-02-06filesystem: remove an outdated commentEric Biggers
2021-12-22filesystem: store mountpoint in link files as a fallbackEric Biggers
Currently, linked protectors use filesystem link files of the form "UUID=<uuid>". These links get broken if the filesystem's UUID changes, e.g. due to the filesystem being re-created even if the ".fscrypt" directory is backed up and restored. To prevent links from being broken (in most cases), start storing the mountpoint path in the link files too, in the form "UUID=<uuid>\nPATH=<path>\n". When following a link, try the UUID first, and if it doesn't work try the PATH. While it's possible that the path changed too, for login protectors (the usual use case of linked protectors) this won't be an issue as the path will always be "/". An alternative solution would be to fall back to scanning all filesystems for the needed protector descriptor. I decided not to do that, since relying on a global scan doesn't seem to be a good design. It wouldn't scale to large numbers of filesystems, it could cross security boundaries, and it would make it possible for adding a new filesystem to break fscrypt on existing filesystems. And if a global scan was an acceptable way to find protectors during normal use, then there would be no need for link files in the first place. Note: this change is backwards compatible (i.e., fscrypt will continue to recognize old link files) but not forwards-compatible (i.e., previous versions of fscrypt won't recognize new link files). Fixes https://github.com/google/fscrypt/issues/311
2021-12-20filesystem: avoid accessing irrelevant filesystemsEric Biggers
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.
2021-12-19Set owner of login protectors to correct userEric Biggers
When the root user creates a login protector for a non-root user, make sure to chown() the protector file to make it owned by the user. Without this, the protector cannot be updated by the user, which causes it to get out of sync if the user changes their login passphrase. Fixes https://github.com/google/fscrypt/issues/319
2020-05-09filesystem: improve errorsEric Biggers
Introduce filesystem.ErrEncryptionNotEnabled and filesystem.ErrEncryptionNotSupported which include the Mount as context, and translate the corresponding metadata/ errors into them. Then make these errors show much better suggestions. Also replace lots of other filesystem/ errors with either custom types or with unnamed one-off errors that include more context. Fix backwards wrapping in lots of cases. Finally, don't include the mountpoint in places where it's not useful, like OS-level errors that already include the path.
2020-05-09actions/policy: improve errorsEric Biggers
ErrMissingPolicyMetadata: Include the mount, directory path, and metadata path. Also move the explanation into actions/ since it doesn't refer to any CLI command. ErrPolicyMetadataMismatch: Include a lot more information. Also start checking for consistency of the policy key descriptors, not just the encryption options. Add a test for this. ErrDifferentFilesystem: Include the mountpoints. ErrOnlyProtector: Clarify the message and include the protector descriptor. ErrAlreadyProtected: ErrNotProtected: Include the policy and protector descriptors. ErrAccessDeniedPossiblyV2: Make it slightly clearer what failed. Also move the explanation into actions/ since it doesn't refer to any CLI command.
2020-05-09cmd/fscrypt: add FSCRYPT_CONSISTENT_OUTPUT environmental variableEric Biggers
Allow setting FSCRYPT_CONSISTENT_OUTPUT=1 in the environment to cause policies and protectors to sorted by last modification time. The CLI tests need this to make the output of 'fscrypt' ordered in a consistent way with regard to the operations performed.
2020-04-16Allow fscrypt to work in containers (#213)Eric Biggers
Update the /proc/self/mountinfo parsing code to allow selecting a Mount with Subtree != "/", i.e. a Mount not of the full filesystem. This is needed to allow fscrypt to work in containers, where the root of the filesystem may not be mounted. See findMainMount() for details about the algorithm used. Resolves https://github.com/google/fscrypt/issues/211
2020-01-28filesystem: don't overwrite existing protector linksEric Biggers
When adding a protector to a policy, don't unconditionally overwrite the protector link, because it may already exist. Instead, if it already exists and points to the mount, just use it. If it already exists and points to the wrong place, return an error. Also add a bool to the return value of AddLinkedProtector() so that callers can check whether the link was newly created or not.
2019-10-30filesystem: handle bind mounts properlyEric Biggers
Currently, fscrypt treats bind mounts as separate filesystems. This is broken because fscrypt will look for a directory's encryption policy in different places depending on which mount it's accessed through. This forces users to create an fscrypt metadata directory at every bind mount, and to copy fscrypt metadata around between mounts. Fix this by storing fscrypt metadata only at the root of the filesystem. To accomplish this: - Make mountsByDevice store only a single Mount per filesystem, rather than multiple. For this Mount, choose a mount of the full filesystem if available, preferably a read-write mount. If the filesystem has only bind mounts, store a nil entry in mountsByDevice so we can show a proper error message later. - Change FindMount() and GetMount() to look up the Mount by device number rather than by path, so that they don't return different Mounts depending on which path is used. - Change AllFilesystems() to not return bind mounts. - Due to the above changes, the mountsByPath map is no longer needed outside of loadMountInfo(). So make it a local variable there. Resolves https://github.com/google/fscrypt/issues/59
2019-10-30filesystem: get correct device for kernel-mounted rootfsEric Biggers
A root filesystem mounted via the kernel command line always has a source of "/dev/root", which isn't a real device node. This makes fscrypt think this filesystem doesn't have a source device, which breaks creating login passphrase-protected directories on other filesystems: fscrypt encrypt: filesystem /: no device for mount "/": system error: cannot create filesystem link This also makes 'fscrypt status' show a blank source device: MOUNTPOINT DEVICE FILESYSTEM ENCRYPTION FSCRYPT / ext4 supported Yes To fix this case, update loadMountInfo() to map the device number to the device name via sysfs rather than use the mount source field.
2019-10-29filesystem: remove Mount.OptionsEric Biggers
fscrypt doesn't currently do anything with the mount options, so remove them from the Mount structure for now.
2019-10-29filesystem: rename Mount.Filesystem to Mount.FilesystemTypeEric Biggers
Make it clear that this refers to a type of filesystem such as "ext4", rather than to a specific filesystem instance.
2019-10-25Added capacity to slice creation, when capacity is known (#159)Vivek V
Simple optimization to reduce memory allocations and copying when appending.
2019-10-01filesystem: allow .fscrypt to be a symlinkEric Biggers
Support the case where the user has a read-only root filesystem (e.g. with OSTree) and had previously created a symlink /.fscrypt pointing to a writable location, so that login protectors can be created there. Resolves https://github.com/google/fscrypt/issues/131
2019-09-09writeDataAtomic() fixes (#140)ebiggers
* filesystem: ensure data is persisted before returning success Sync the temporary file before renaming it, to ensure that after a crash, the destination file isn't zero-length or otherwise incomplete. Also sync the directory after the rename, to ensure the rename has been persisted before returning success. * filesystem: don't use fixed temporary file name Using a fixed temporary file name in a world-writable sticky directory is problematic since another user can create the file first. Use ioutil.TempFile() to do it properly. It uses O_EXCL under the hood to ensure the file is newly created.
2019-09-08Fix various typos and grammatical errors (#141)ebiggers
These were found by a combination of manual review and a custom script that checks for common errors. Also removed an outdated sentence from the comment for setupBefore().
2017-08-31filesystem: libblkid -> search /dev/disk/by-uuidJoe Richey
2017-07-17filesystem: Distinguish support and setup for fsJoe Richey joerichey@google.com
This commit splits two pieces of functionality. Detecting if the fscrypt metadata exists is now in CheckSetup() and checking if the filesystem supports encryption is now in CheckSupport().
2017-06-28Finalize import paths and documentationv0.1.00.1.0Joe Richey joerichey@google.com
This commit changes all the internal import paths from `fscrypt/foo` to `github.com/google/fscrypt/foo` so that it can be built once we release externaly. The documentation in README.md is updated accordingly. Also, the README has a note noting that we do not make any guarantees about project stability before 1.0 (when it ships with Ubuntu). Change-Id: I6ba86e442c74057c8a06ba32a42e17f94833e280
2017-06-28Change error handling to new packageJoe Richey joerichey@google.com
This commit changes the error handing for the crypto, filesystem, metadata, pam, and util packages to use the error handling library github.com/pkg/errors. This means elimination of the FSError type, an increased use of wrapping errors (as opposed to logging), switching on the Cause() of an error (as opposed to its value), and improving our integration tests involving TEST_FILESYSTEM_ROOT. This commit also fixes a few bugs with the keyring code to ensure that our {Find|Remove|Insert}PolicyKey functions are always operating on the same keyring. The check for filesystem support has been moved from the filesystem package to the metadata package. Finally, the API for the filesystem package has been slightly modified: * filesystem.AllFilesystems() now returns all the filesystems in sorted order * certain path methods are now public O_SYNC is also removed for writing the metadata. We don't get that much from syncing the metadata, as the actual file data could also be corrupted by and IO error. The sync operation is also occasionally very slow (~3 seconds) and can be unfriendly to battery life. Change-Id: I392c2655141714b16dfdbc84ac09780072be2cf0
2017-06-15filesystem: change support detection and bug-fixesJoe Richey joerichey@google.com
Instead of checking if the filesystem type is correct, we now detect if a filesystem supports encryption by trying to read a policy on its root directory. The error returned tells us if there is support or not. This commit also fixes a bug in the use libblkid. Throughout all of fscrypt, cannonicalizePath() is used before any path comparison or lookup. However, the canonical device path in the blkid cache may differ from our idea of a canonical path. Additional blkid functions are needed to perform the necessary translation. This is noted in the documentation of makeLink(). Finally, this commit makes a few API changes. AllSupporedFilesystems() now returns an error, and a GetProtector() method now replaces the GetLinkedProtector() and GetEitherProtector() methods. A PathSorter has also been added so Mounts can be sorted in a reliable order. Change-Id: I664f46fafd1483ebecb743c061b03d708b3233a4
2017-05-31filesystem: creating the directories and filesJoe Richey joerichey@google.com
This commit adds in the filesystem subpackage. The goal of this package is to provide and interface for adding to and removing from the metadata storage for a given filesystem. This is primarily done in filesystem.go. To facilitate this functionality, mountpoint.go exposes an interface for querying the system about the current mounted filesystems and their information. Note that this operation is done with a lazy loading mechanism. To refer to other filesystems, we use link files that can be parsed by libblkid. The README is also updated to account for this new dependancy. This package uses the FSError type under the hood so that error messages will include the filesystem name, but callers can still check for specific error instances. Change-Id: I74fe4e84b8e3a5b73f1337c35307ffe0bf7cdea9