Eric Biggers [Tue, 29 Oct 2019 07:04:39 +0000 (00:04 -0700)]
filesystem: get correct device for kernel-mounted rootfs
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:
Eric Biggers [Tue, 29 Oct 2019 07:04:39 +0000 (00:04 -0700)]
filesystem: switch to using /proc/self/mountinfo
Change loadMountInfo() to load the mounts directly from
/proc/self/mountinfo, rather than use the mntent.h C library calls.
This is needed for correct handling of bind mounts and of "/dev/root",
since /proc/self/mountinfo has extra fields which show the mounted
subtree and the filesystem's device number. /proc/mounts lacks these
fields, and the C library calls can't provide them.
To start, this patch just switches to using /proc/self/mountinfo,
without doing anything with the extra fields yet.
As a bonus, this eliminates all C code in mountpoint.go.
Joseph Richey [Sat, 26 Oct 2019 00:15:27 +0000 (17:15 -0700)]
Delete vendored code and update CI to Go 1.13 (#158)
As the Go community transitions to using the modules ecosystem,
we want to only support one way of managing dependencies.
So this change moves to only using Go modules for dependency management.
This means that our effective minimum Go version increases to Go 1.11.
To account for this, we also update:
- the documentation
- Makefile
- CI scripts
ebiggers [Thu, 24 Oct 2019 05:18:45 +0000 (22:18 -0700)]
actions/config: ensure config file is created with mode 0644 (#152)
If the user has set a restrictive umask, e.g. 0077, then
/etc/fscrypt.conf would be created without the world-readable bit set.
Fix it by overriding the umask when creating the file.
Eric Biggers [Tue, 1 Oct 2019 16:43:36 +0000 (09:43 -0700)]
filesystem: allow .fscrypt to be a symlink
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.
cmd/fscrypt: make 'fscrypt setup' create /.fscrypt (#149)
Make the global setup command also create the metadata directory at
/.fscrypt, since that's where login protectors are placed, even when the
actual encrypted directories are on a different filesystem.
Joe Richey [Sun, 20 Jan 2019 03:27:30 +0000 (19:27 -0800)]
Install pam modules/configs to the right location
Per the FHS, manually installed programs should go under /usr/local.
This change also makes it easier to change the global installation
prefix. For example, package managers should set PREFIX=/usr
Eric Biggers [Tue, 15 Jan 2019 02:43:25 +0000 (18:43 -0800)]
Add support for the Adiantum encryption mode
Add Adiantum support to the fscrypt userspace tool. Supported in the
kernel since v5.0-rc1, Adiantum is a length-preserving encryption mode
based primarily on XChaCha12. It is fast even on CPUs without AES
instructions. Unlike XTS it is also a wide-block encryption mode.
Adiantum is supported for both contents and filenames encryption.
For Adiantum encryption policies, also make the fscrypt tool provide the
new DIRECT_KEY flag, which further improves performance by requesting
that all files be encrypted directly with the policy key. This takes
advantage of Adiantum's support for long tweaks.
See the kernel commit "fscrypt: add Adiantum support"
(https://git.kernel.org/torvalds/c/8094c3ceb21ad938) for more details.
Eric Biggers [Tue, 4 Dec 2018 22:31:20 +0000 (14:31 -0800)]
Makefile: use a specific protoc-gen-go version
'make gen' no longer works because it uses the git version of
protoc-gen-go, which is no longer compatible with the latest released
version of github.com/golang/protobuf/proto, which we're using. Freeze
the protoc-gen-go version so that it keeps working.
This change makes sure that, when we set the ruid and euid in order to
get the user keyring linked into the current process keyring, we will
always be able to reverse these changes (using a suid of 0).
This fixes an issue where "su <user>" would result in a system error
when called by an unprivileged user. It also explains exactly how and
why we are making these privilege changes.
This change makes sure after dropping then elevating privileges for a
process, the euid, guid, and groups are all the same as they were
originally. This significantly simplifies the privilege logic.
This fixes CVE-2018-6558, which allowed an unprivleged user to gain
membership in the root group (gid 0) due to the groups not being
properly reset in the process.
Eric Biggers [Sun, 25 Mar 2018 17:13:26 +0000 (10:13 -0700)]
security: drop and regain privileges in all threads
After enabling pam_fscrypt for "session" and creating a directory
protected with a login protector, I was no longer able to log in as that
user. The problem is that the Go runtime is creating threads after
pam_fscrypt drops privileges, but pam_fscrypt is not re-acquiring
privileges on those threads because the Go wrappers for setreuid(),
setregid(), and setgroups() in the "sys/unix" package are using the raw
syscalls which operate on the calling thread only.
This violates glibc's assumption that all threads have the same uids and
gids, causing it to abort() the process when a later module in the PAM
stack (pam_mail in my case) tries to drop privileges using the glibc
functions.
Fix it by dropping and regaining privileges using the glibc functions
rather than the "sys/unix" functions.
This also avoids any possibility that privileges could be changed in a
thread other than the "main" one for pam_fscrypt, since the Go runtime
does not guarantee which OS-level thread runs what.
It would be nice to also exit all Go worker threads before returning
from pam_fscrypt, but the Go runtime doesn't seem to support that.
Eric Biggers [Sun, 25 Mar 2018 06:21:29 +0000 (23:21 -0700)]
pam: return error when PAM info item is unset
pam_fscrypt is crashing with a segfault in copyIntoSecret() when using
Ctrl-C to interrupt a 'sudo' prompt. It is dereferencing a NULL pointer
that is supposed point to the PAM_AUTHTOK item. The problem is that the
Go code assumes pam_get_item() returns a non-success status if the item
is unset, when actually it sets the data pointer to NULL and returns
PAM_SUCCESS.
Fix it by making pam.Handle.GetItem() return an error in that case.
Joseph Richey [Mon, 12 Feb 2018 05:22:53 +0000 (21:22 -0800)]
travis: use multiple build stages
This change rewrites .travis.yml to use many build stages/jobs. This
allows our build to run faster, as almost all jobs run in containers.
Stage 1: Run on all pushes to all branches
- Job Build: just runs "make" to make sure everything is OK
Stage 2: Run on all PRs and pushes to master
- Job Lint: Makes sure dep, "make gen", "make format", and "make lint"
are all happy.
- Job Build 1: Make sure "go get" and "make" will work. This job will
later run unit tests.
- Job Build 2: Same as Job Build 1, except with another go version.
- Job Integeration: Run integration tests (needs sudo, so needs VM)
Stage 3: Run on releases (if other stages pass)
- Job Deploy: Publishes amd64 binaries to GitHub.
Joseph Richey [Mon, 12 Feb 2018 05:06:32 +0000 (21:06 -0800)]
Makefile: completly rewrite
This change is a complete rewrite of fscrypt's Makefile.
The new build rules can be roughly divided into secions:
Build - bin/fscrypt and bin/pam_fscrypt
Linting - gen (for .proto files), format, lint
Test - test, test-{setup|teardown}, coverage.out
Install - install, uninstall, install-{bin|pam}
Tools - tools and other bin/* needed for the other rules
As before, "make" builds the binary and pam_module, while "make all"
builds and tests everything (except for integration tests), and "make
clean" removes any generated files.
Also note that this new build system:
- Doesn't require input_fail.py
- Properly falis on linter errors
- Builds everything into the bin/ directory (customizable)
- Builds all the vendored tools
Joseph Richey [Mon, 12 Feb 2018 04:39:12 +0000 (20:39 -0800)]
golint: Use fork that respects vendor directory
Ideally, we would just use "golint ./..." to check all our our source
files for lint error. However, this does not work because it will
include all packages in the vendor directory. The pull request at:
https://github.com/golang/lint/pull/325
fixes this issue, so we will use it until the PR has been merged.
Joseph Richey [Mon, 12 Feb 2018 04:31:27 +0000 (20:31 -0800)]
dep: require tools to be vendored
This change ot Gopkg.toml will make it easier to build the linting and
formatting tools. Vendoring their source also makes sure that updates to
these tools do not break the build.
Joseph Richey [Mon, 12 Feb 2018 04:24:21 +0000 (20:24 -0800)]
dep: add dependancies to Gopkg.toml
fscrypt directly depends on 5 repositories (8 packages). This change
adds those dependancies to Gopkg.toml, so that they can be properly
versioned. Note that the golang.org/x repositories do not use semver.
Joseph Richey [Mon, 12 Feb 2018 04:19:36 +0000 (20:19 -0800)]
test: all packages should have tests
The tests added in this change are trivial, but they make sure that
every package has a non-zero number of tests. This is important for
eventually increasing test coverage.
Joseph Richey [Fri, 9 Feb 2018 09:51:44 +0000 (01:51 -0800)]
docs/travis: Remove mention of Argon2
Now that Argon2 is simply and implementation detail of the `crypto`
package, and no a build dependancy, we don't need it in Travis or in the
documenation for building fscrypt.
Joseph Richey [Thu, 8 Feb 2018 10:37:42 +0000 (02:37 -0800)]
crypto: Move from libargon2 -> x/crypto/argon2
Use the golang library for the hashing function instead of the reference
C implementation. This removes the dependancy on libargon2. As we are no
longer doing our own error checking, we also eliminate those tests.