| Age | Commit message (Collapse) | Author |
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
fscrypt doesn't currently do anything with the mount options, so remove
them from the Mount structure for now.
|
|
Make it clear that this refers to a type of filesystem such as "ext4",
rather than to a specific filesystem instance.
|
|
Simple optimization to reduce memory allocations and copying when appending.
|
|
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
|
|
* 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.
|
|
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().
|
|
|
|
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().
|
|
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
|
|
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
|
|
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
|
|
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
|