Commit Graph

121 Commits

Author SHA1 Message Date
Jakob Unterwurzacher
3d54fc3a3a fusefrontend: create helpers for symlink encryption
These will be reused by the upcoming xattr support.
2018-03-24 21:40:11 +01:00
Jakob Unterwurzacher
719693ec5d fusefrontend[_reverse]: move crypto init up to caller
Both fusefrontend and fusefrontend_reverse were doing
essentially the same thing, move it into main's
initFuseFrontend.

A side-effect is that we have a reference to cryptocore
in main, which will help with wiping the keys on exit
(https://github.com/rfjakob/gocryptfs/issues/211).
2018-02-18 11:21:58 +01:00
Jakob Unterwurzacher
8951eb2472 fusefronted: add PlaintextNames special-cases for Create & Rename
gocryptfs.longname.XXX files were considered magic in PlaintextNames
mode, which was wrong.

Fix that and add tests.

Fixes https://github.com/rfjakob/gocryptfs/issues/174
2018-01-17 00:25:36 +01:00
Sebastian Lackner
a85dbcab38 fusefrontend: Use Linkat syscall to implement Link 2017-12-25 15:07:37 +01:00
Sebastian Lackner
a24342f656 fusefrontend: Handle PlaintextNames mode in Link
In PlaintextNames mode the "gocryptfs.longname." prefix does not have any
special meaning.

https://github.com/rfjakob/gocryptfs/issues/174
2017-12-25 15:07:37 +01:00
Jakob Unterwurzacher
e97c23e083 syscallcompat: check that we get NOFOLLOW wherever possible
...and fix the instances where the AT_SYMLINK_NOFOLLOW /
O_NOFOLLOW / O_EXCL flag was missing.
2017-11-30 19:40:53 +01:00
Sebastian Lackner
67bcbe81e8 fusefrontend: Use Fchownat to implement Chown 2017-11-29 13:05:46 +01:00
Sebastian Lackner
0162392a28 fusefrontend: Use Fchmodat to implement Chmod 2017-11-29 12:55:41 +01:00
Sebastian Lackner
0f44c617d0 syscallcompat: Introduce unlinkat syscall with flags argument 2017-11-29 12:41:23 +01:00
Sebastian Lackner
5d44a31b41 fusefrontend: Use openBackingPath in Unlink and simplify code 2017-11-28 09:28:06 +01:00
Sebastian Lackner
2591900b69 fusefrontend: Handle PlaintextNames mode in Unlink
In PlaintextNames mode the "gocryptfs.longname." prefix does not have any
special meaning. We should not attempt to delete any .name files.

Partially fixes https://github.com/rfjakob/gocryptfs/issues/174
2017-11-28 09:28:06 +01:00
Sebastian Lackner
eba49402e4 fusefrontend: Introduce a openBackingPath helper and use it to simplify Mknod and Symlink 2017-11-28 09:28:06 +01:00
Sebastian Lackner
ad2720e0f9 fusefrontend: allow_other: close race between symlink and chown
Fixes the same problem as described in 72b975867a,
except for symlinks instead of device nodes.
2017-11-28 09:28:06 +01:00
Sebastian Lackner
5a56810603 fusefrontend: Use the Symlinkat syscall for longname handling 2017-11-28 09:28:06 +01:00
Sebastian Lackner
295c4c2b85 fusefrontend: Set owner after symlink creation in PlaintextNames mode
This is already done in regular mode, but was missing when PlaintextNames mode
is enabled. As a result, symlinks created by non-root users were still owned
by root afterwards.

Fixes https://github.com/rfjakob/gocryptfs/issues/176
2017-11-28 09:28:06 +01:00
Sebastian Lackner
3f68b0c09a fusefrontend: Handle PlaintextNames mode in Mknod
In PlaintextNames mode the "gocryptfs.longname." prefix does not have any
special meaning. We should not attempt to read the directory IV or to
create special .name files.

Partially fixes https://github.com/rfjakob/gocryptfs/issues/174
2017-11-28 09:28:06 +01:00
Jakob Unterwurzacher
72b975867a fusefronted: allow_other: close race between mknod and chown
If the user manages to replace the directory with
a symlink at just the right time, we could be tricked
into chown'ing the wrong file.

This change fixes the race by using fchownat, which
unfortunately is not available on darwin, hence a compat
wrapper is added.

Scenario, as described by @slackner at
https://github.com/rfjakob/gocryptfs/issues/177 :

1. Create a forward mount point with `plaintextnames` enabled
2. Mount as root user with `allow_other`
3. For testing purposes create a file `/tmp/file_owned_by_root`
   which is owned by the root user
4. As a regular user run inside of the GoCryptFS mount:

```
mkdir tempdir
mknod tempdir/file_owned_by_root p &
mv tempdir tempdir2
ln -s /tmp tempdir
```

When the steps are done fast enough and in the right order
(run in a loop!), the device file will be created in
`tempdir`, but the `lchown` will be executed by following
the symlink. As a result, the ownership of the file located
at `/tmp/file_owned_by_root` will be changed.
2017-11-27 21:04:45 +01:00
Sebastian Lackner
9f56b33e0c fusefrontend: Fix longname handling for renames with existing target
Fixes https://github.com/rfjakob/gocryptfs/issues/170

Steps to reproduce the problem:

* Create a regular forward mount point
* Create a file with a shortname and one with a long filename
* Try to run 'mv <shortname> <longname>'

This should actually work and replace the existing file, but instead it
fails with:

    mv: cannot move '<shortname>' to '<longname>': File exists

The problem is the creation of the .name file. If the target already exists
we can safely ignore the EEXIST error and just keep the existing .name file.
2017-11-25 16:19:09 +01:00
Jakob Unterwurzacher
0c520845f3 main: purge masterkey from memory as soon as possible
Remove the "Masterkey" field from fusefrontend.Args because it
should not be stored longer than neccessary. Instead pass the
masterkey as a separate argument to the filesystem initializers.

Then overwrite it with zeros immediately so we don't have
to wait for garbage collection.

Note that the crypto implementation still stores at least a
masterkey-derived value, so this change makes it harder, but not
impossible, to extract the encryption keys from memory.

Suggested at https://github.com/rfjakob/gocryptfs/issues/137
2017-08-11 19:02:26 +02:00
Jakob Unterwurzacher
3062de6187 fusefronted: enable writing to write-only files
Due to RMW, we always need read permissions on the backing file. This is a
problem if the file permissions do not allow reading (i.e. 0200 permissions).
This patch works around that problem by chmod'ing the file, obtaining a fd,
and chmod'ing it back.

Test included.

Issue reported at: https://github.com/rfjakob/gocryptfs/issues/125
2017-07-11 23:19:58 +02:00
Charles Duffy
cf1ded5236 Implement force_owner option to display ownership as a specific user. 2017-06-01 00:26:17 +02:00
Jakob Unterwurzacher
c52e1abc58 fusefrontend: log "too many open files" errors
This usually indicates that the open file limit for gocryptfs is
too low. We should report this to the user.
2017-05-03 23:46:52 +02:00
Jakob Unterwurzacher
9ab11aa4d7 fusefrontend: drop writeOnly flag
We do not have to track the writeOnly status because the kernel
will not forward read requests on a write-only FD to us anyway.

I have verified this behavoir manually on a 4.10.8 kernel and also
added a testcase.
2017-05-01 17:49:37 +02:00
Jakob Unterwurzacher
edb3e19cb5 fix golint complaints 2017-04-29 14:50:58 +02:00
danim7
f1945c4daa Add -forcedecode
Force decode of encrypted files even if the integrity check fails, instead of
failing with an IO error. Warning messages are still printed to syslog if corrupted
files are encountered.
It can be useful to recover files from disks with bad sectors or other corrupted
media.

Closes https://github.com/rfjakob/gocryptfs/pull/102 .
2017-04-23 23:11:56 +02:00
Jakob Unterwurzacher
00df0771e3 serialize_reads: add read serialization logic
Due to kernel readahead, we usually get multiple read requests
at the same time. These get submitted to the backing storage in
random order, which is a problem if seeking is very expensive.

Details: https://github.com/rfjakob/gocryptfs/issues/92
2017-03-18 16:18:00 +01:00
Jakob Unterwurzacher
445b5019e3 nametransform: fix Raw64 not affecting symlink targets
The symlink functions incorrectly hardcoded the padded
base64 variant.
2017-03-05 22:59:25 +01:00
Jakob Unterwurzacher
d0bc7970f7 full stack: implement HKDF support
...but keep it disabled by default for new filesystems.

We are still missing an example filesystem and CLI arguments
to explicitely enable and disable it.
2017-03-05 21:59:55 +01:00
Jakob Unterwurzacher
e032539e2c cryptocore: use eme v1.1 interface
Version 1.1 of the EME package (github.com/rfjakob/eme) added
a more convenient interface. Use it.

Note that you have to upgrade your EME package (go get -u)!
2017-03-05 13:58:24 +01:00
Jakob Unterwurzacher
b2f3dbb8bd fusefrontend: when chown'ing a directory, also chown its diriv
When filename encryption is active, every directory contains
a "gocryptfs.diriv" file. This file should also change the owner.

Fixes https://github.com/rfjakob/gocryptfs/issues/86
2017-03-02 19:12:21 +01:00
Jakob Unterwurzacher
a7c7588deb fusefrontend: fix hard-linking with long name
This used to incorrectly try to link twice and return EEXIST.
2017-01-26 20:56:42 +01:00
Jakob Unterwurzacher
55df8acac3 fusefrontend: preserve owner for symlinks
https://github.com/rfjakob/gocryptfs/issues/64
2016-11-28 23:15:24 +01:00
Jakob Unterwurzacher
e3c5e3f1c8 fusefronted: preserve owner for device nodes and sockets
https://github.com/rfjakob/gocryptfs/issues/64
2016-11-28 23:09:47 +01:00
Jakob Unterwurzacher
a66440c668 fusefrontend: use Lchown when preserving owner
This prevents (unlikely) symlink race attacks
2016-11-28 22:46:04 +01:00
Jakob Unterwurzacher
0f8d3318a3 main, fusefrontend: add "-noprealloc" option
Preallocation is very slow on hdds that run btrfs. Give the
user the option to disable it. This greatly speeds up small file
operations but reduces the robustness against out-of-space errors.

Also add the option to the man page.

More info: https://github.com/rfjakob/gocryptfs/issues/63
2016-11-25 09:19:14 +01:00
Jakob Unterwurzacher
2b991c9743 Add support for unpadded base64 filenames, "-raw64"
Through base64.RawURLEncoding.

New command-line parameter "-raw64".
2016-11-01 18:43:22 +01:00
Jakob Unterwurzacher
828f718483 fusefrontend: Also preserve the owner in Mkdir
This already worked for files but was missing for dirs.
2016-10-10 08:53:29 +02:00
Valient Gough
b764917cd5 lint fixes 2016-10-04 23:18:33 +02:00
Jakob Unterwurzacher
a2510efe12 reverse: use per-purpose nonce generation
Also pull all the deterministic nonce code into fusefrontend_reverse
to greatly simplify the normal code path.
2016-09-29 21:56:49 +02:00
Jakob Unterwurzacher
abd61d968d contentenc: rename constant "IVBitLen" to "DefaultIVBits" and clarify comment
128-bit IVs are NOT used everywhere.
2016-09-25 18:40:29 +02:00
Jakob Unterwurzacher
12808138ef contentenc: add "ExternalNonce" mode
This will be used for strong symlink encryption in reverse mode.
2016-09-25 17:44:19 +02:00
Jakob Unterwurzacher
32e55261ca fusefrontend: handle Readlink directly
Calling into go-fuse's loopbackFileSystem does not add
any value here.
2016-09-25 17:01:39 +02:00
Jakob Unterwurzacher
5f726aaa9d contentenc: add GCM-SIV support
Also add ReverseDummyNonce nonce generation.
2016-09-25 16:43:17 +02:00
Jakob Unterwurzacher
7f87ed78f2 cryptocore: add support for GCM-SIV 2016-09-25 16:43:17 +02:00
Jakob Unterwurzacher
fca1b82417 fusefrontend: relay Utimens to go-fuse
Commit af5441dcd9 has caused a
regression ( https://github.com/rfjakob/gocryptfs/issues/35 )
that is fixed by this commit.

The go-fuse library by now has all the syscall wrappers in
place to correctly handle Utimens, also for symlinks.

Instead of duplicating the effort here just call into go-fuse.

Closes #35
2016-09-25 16:30:29 +02:00
Jakob Unterwurzacher
af5441dcd9 fusefrontend: use NsecToTimespec() for Utimens
This fixes a build problem on 32-bit hosts:

  internal/fusefrontend/file.go:400: cannot use a.Unix() (type int64) as
  type int32 in assignment
  internal/fusefrontend/file.go:406: cannot use m.Unix() (type int64) as
  type int32 in assignment

It also enables full nanosecond timestamps for dates
after 1970.
2016-08-09 22:18:46 +02:00
Jakob Unterwurzacher
e8a234f658 Add godoc comments to all internal packages 2016-07-06 21:51:25 +02:00
Jakob Unterwurzacher
741bf0726e syscallcompat: OSX: add Mknodat wrapper
Protip: find naked *at syscalls using:

   git grep "syscall." | grep "at(" | grep -v syscallcompat
2016-07-03 20:22:22 +02:00
Jakob Unterwurzacher
d8524c7369 syscallcompat: OSX: add Unlinkat wrapper
Also, replace remaining naked syscall.Openat calls.
2016-07-03 20:17:40 +02:00
Jakob Unterwurzacher
1d7728959c fusefrontend: downgrade Renameat log message to debug 2016-07-03 20:08:09 +02:00
Jakob Unterwurzacher
79851bf6cc syscallcompat: OSX: add Renamat wrapper
Adds a poor man's renameat implementation for OSX.
2016-07-03 20:05:32 +02:00
Jakob Unterwurzacher
e994ffa27d fusefrontend: handle dir-overwrites-dir on XFS
XFS returns a different error code if you try to overwrite
a non-empty directory with a directory:

XFS:  mv: cannot move ‘foo’ to ‘bar/foo’: File exists
ext4: mv: cannot move 'foo' to 'bar/foo': Directory not empty

So have EEXIST trigger the Rmdir logic as well.

Fixes issue #20
Link: https://github.com/rfjakob/gocryptfs/issues/20
2016-06-30 23:17:54 +02:00
Jakob Unterwurzacher
0115588680 main, fusefrontend: enable suid functionality
FUSE filesystems are mounted with "nosuid" by default. If we run as root,
we can use device files by passing the opposite mount option, "suid".

Also we have to use syscall.Chmod instead of os.Chmod because the
portability translation layer "syscallMode" messes up the sgid
and suid bits.

Fixes 70% of the failures in xfstests generic/193. The remaining are
related to truncate, but we err on the safe side:

    $ diff -u tests/generic/193.out /home/jakob/src/fuse-xfstests/results//generic/193.out.bad
    [...]
     check that suid/sgid bits are cleared after successful truncate...
     with no exec perm
     before: -rwSr-Sr--
    -after:  -rw-r-Sr--
    +after:  -rw-r--r--
2016-06-26 20:13:21 +02:00
Jakob Unterwurzacher
23cc0657f4 fusefronted: preserve owner if running as root
If allow_other is set and we run as root, try to give newly created files to
the right user.
2016-06-26 19:18:13 +02:00
Jakob Unterwurzacher
38767ab527 fuserfrontend: support truncate(2) by wrapping ftruncate(2)
Support truncate(2) by opening the file and calling ftruncate(2)
While the glibc "truncate" wrapper seems to always use ftruncate, fsstress from
xfstests uses this a lot by calling "truncate64" directly.
2016-06-26 18:41:04 +02:00
Jakob Unterwurzacher
b558901e66 Drop deprecated "-gcmiv128" option
The GCMIV128 feature flag is already mandatory, dropping the command
line option is the final step.

Completes https://github.com/rfjakob/gocryptfs/issues/29 .
2016-06-23 22:10:19 +02:00
Jakob Unterwurzacher
3d59a72ba9 Drop deprecated "-emenames" option
The EMENames feature flag is already mandatory, dropping the command
line option is the final step.
2016-06-23 21:56:50 +02:00
Jakob Unterwurzacher
b17f0465c7 Drop deprecated "-diriv" option
The DirIV feature flag is already mandatory, dropping the command
line option is the final step.
2016-06-23 21:38:59 +02:00
Jakob Unterwurzacher
6c3f97399a Rename internal "toggledlog" package to "tlog"
tlog is used heavily everywhere and deserves a shorter name.

Renamed using sed magic, without any manual rework:

   find * -type f -exec sed -i 's/toggledlog/tlog/g' {} +
2016-06-15 23:30:44 +02:00
Jakob Unterwurzacher
5da292828c fusefrontend: fix chown on dangling symlinks
We (actually, go-fuse) used to call Chown() instead of Lchown()
which meant that the operation would fail on dangling symlinks.

Fix this by calling os.Lchown() ourself. Also add a test case
for this.
2016-06-08 00:32:44 +02:00
Jakob Unterwurzacher
1648c54adb fusefrontend: use sync.Once for one-time warnings
Using a simple boolean was racy (which was harmless
in this case) and non-idomatic.
2016-05-29 22:50:03 +02:00
Jakob Unterwurzacher
fd53dfd2ad fusefronted: check Fstat return value on file create
The Fstat call should never fail, but still, if it does return an error
it should be handled properly.
2016-05-29 22:43:48 +02:00
David Gnedt
a93bcabe9c Encrypt path in statfs() calls
Paths in statfs() calls were not encrypted resulting in
an Function not implemented error, when the unencrypted
path didn't exist in the underlying (encrypted)
filesystem.

$ df plain/existingdir
df: ‘plain/existingdir’: Function not implemented
2016-05-12 23:24:39 +02:00
Jakob Unterwurzacher
bd5405189e Fix "go tool vet -shadow=true" warnings
Among those one real bug.
2016-04-10 21:31:15 +02:00
Jakob Unterwurzacher
db72fcea41 longnames: fix fsstress failure, use dirfd
Using dirfd-relative operations allows safe lockless handling
of the ".name" files.
2016-04-10 21:31:08 +02:00
Jakob Unterwurzacher
653d4a619c longnames part II: Rename, Unlink, Rmdir, Mknod, Mkdir + tests 2016-02-07 14:02:09 +01:00
Jakob Unterwurzacher
6b5d977cce Move OpenDir to fs_dir.go 2016-02-07 11:29:54 +01:00
Jakob Unterwurzacher
e111e20649 longnames part I: Create and OpenDir work with long filenames > 176 bytes
Todo: Rename, Unlink, Rmdir, Mknod, Mkdir
2016-02-06 22:54:14 +01:00
Jakob Unterwurzacher
c74772bc8d Run go fmt 2016-02-06 20:23:36 +01:00
Jakob Unterwurzacher
b0ee5258b1 Fix tests - were broken by the refactoring 2016-02-06 20:22:45 +01:00
Jakob Unterwurzacher
9078a77850 Move pathfs_frontend to internal/fusefrontend
"git status" for reference:

renamed:    pathfs_frontend/args.go -> internal/fusefrontend/args.go
renamed:    pathfs_frontend/compat_darwin.go -> internal/fusefrontend/compat_darwin.go
renamed:    pathfs_frontend/compat_linux.go -> internal/fusefrontend/compat_linux.go
renamed:    pathfs_frontend/file.go -> internal/fusefrontend/file.go
renamed:    pathfs_frontend/file_holes.go -> internal/fusefrontend/file_holes.go
renamed:    pathfs_frontend/fs.go -> internal/fusefrontend/fs.go
renamed:    pathfs_frontend/fs_dir.go -> internal/fusefrontend/fs_dir.go
renamed:    pathfs_frontend/names.go -> internal/fusefrontend/names.go
renamed:    pathfs_frontend/write_lock.go -> internal/fusefrontend/write_lock.go
modified:   main.go
2016-02-06 19:27:59 +01:00