Commit Graph

127 Commits

Author SHA1 Message Date
Jakob Unterwurzacher ec74d1d2f4 Update go-fuse import path to github.com/hanwen/go-fuse/v2
We need
fd7328faf9
to fix a crash reported in https://github.com/rfjakob/gocryptfs/issues/430 :

  2019/10/30 17:14:16 Unknown opcode 2016
  panic: runtime error: invalid memory address or nil pointer dereference
  [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x508d38]

This patch is only in the v2.x.x branch. Upgrade to v2, as the
old API is also supported there.

Running

  git grep hanwen/go-fuse | grep -v hanwen/go-fuse/v2

to check for forgotten references comes back clean.
2020-05-17 14:23:47 +02:00
Jakob Unterwurzacher 9f9d59ded9 inomap: rework logic to efficiently support flags
Adding flags allows to use inomap in reverse mode,
replacing the clunky inoBaseDirIV/inoBaseNameFile
logic that causes problems with high underlying
inode numbers ( https://github.com/rfjakob/gocryptfs/issues/457 )

Microbenchmarks (values below) show that the "SingleDev"
case is now much slower due to an extra map lookup,
but this has no visible effects in ./test.bash results,
so there was no time spent optimizing the case further.

$ go test -bench=.
goos: linux
goarch: amd64
pkg: github.com/rfjakob/gocryptfs/internal/inomap
BenchmarkTranslateSingleDev-4   	18757510	        61.5 ns/op
BenchmarkTranslateManyDevs-4    	18061515	        64.5 ns/op
PASS
ok  	github.com/rfjakob/gocryptfs/internal/inomap	2.467s
2020-04-19 22:00:56 +02:00
Jakob Unterwurzacher 488111ce39 inomap: split into separate package
inomap will also be used by fusefrontend_reverse
in the future. Split if off openfiletable to make
it independent.
2020-04-13 14:54:04 +02:00
Jakob Unterwurzacher 8ec804d825 fs: add uint64 cast to fix Darwin build
Error from Travis CI was:

 +GOOS=darwin
 +GOARCH=amd64
 +go build -tags without_openssl
 # github.com/rfjakob/gocryptfs/internal/fusefrontend
 internal/fusefrontend/fs.go:88:45: cannot use st.Dev (type int32) as type uint64 in argument to openfiletable.NewInumMap

Add uint64 to fix it.
2019-11-16 23:21:37 +01:00
Jakob Unterwurzacher bb6155a51f fusefrontend: use inummap
translate inode numbers on different devices to fix
collisions.

Fixes https://github.com/rfjakob/gocryptfs/issues/435
2019-11-16 21:36:27 +01:00
Jakob Unterwurzacher 0a4db7d9e9 Fix -idle unmounting despite activity
Fixes https://github.com/rfjakob/gocryptfs/issues/421
2019-09-08 16:29:20 +02:00
Eduardo M KALINOWSKI 3bc100aeb3 reverse mode: support wildcard exclude (--exclude-wildcard)
This adds support for gitignore-like wildcards and exclude patters in
reverse mode. It (somewhat) fixes #273: no regexp support, but the
syntax should be powerful enough to satisfy most needs.

Also, since adding a lot of --exclude options can be tedious, it adds
the --exclude-from option to read patterns from a file (or files).
2019-03-26 20:56:37 +01:00
Jakob Unterwurzacher b08cbce5c1 fusefronted: comment why Access() does not check context.Uid
https://github.com/rfjakob/gocryptfs/issues/347
2019-01-20 14:37:36 +01:00
Jakob Unterwurzacher 3d6b2685fb Revert "syscallcompat: drop Faccessat AT_SYMLINK_NOFOLLOW helper"
Breaks mounting on MacOS: unix.Faccessat on Darwin does NOT (yet)
support AT_SYMLINK_NOFOLLOW. See d44fe89ba4 .

This reverts commit 0805a63df1.
2019-01-20 13:10:59 +01:00
Jakob Unterwurzacher 0805a63df1 syscallcompat: drop Faccessat AT_SYMLINK_NOFOLLOW helper
unix.Faccessat has added support for AT_SYMLINK_NOFOLLOW in July 2018,
bd9dbc187b (diff-341484dbbe3180cd7a31ef2ad2d679b6)
which means we no longer need our own helper.

Closes https://github.com/rfjakob/gocryptfs/issues/347
2019-01-20 12:59:59 +01:00
Sebastian Lackner 682e642cfa fusefrontend: Rework the Utimens handling on macOS.
For Linux, everything effectively stays the same. For both path-based and
fd-based Utimens() calls, we use unix.UtimesNanoAt(). To avoid introducing
a separate syscall wrapper for futimens() (as done in go-fuse, for example),
we instead use the /proc/self/fd - trick.

On macOS, this changes quite a lot:

* Path-based Utimens() calls were previously completely broken, since
  unix.UtimensNanoAt() ignores the passed file descriptor. Note that this
  cannot be fixed easily since there IS no appropriate syscall available on
  macOS prior to High Sierra (10.13). We emulate this case by using
  Fchdir() + setattrlist().

* Fd-based Utimens() calls were previously translated to f.GetAttr() (to
  fill any empty parameters) and syscall.Futimes(), which does not does
  support nanosecond precision. Both issues can be fixed by switching to
  fsetattrlist().

Fixes https://github.com/rfjakob/gocryptfs/issues/350
2019-01-16 20:55:20 +01:00
Sebastian Lackner 8f33145651 fusefrontend: Print 'too many open files' warning for both short and long names.
While we're at it, also replace os.* constants with syscall.* constants.
2019-01-15 22:07:37 +01:00
Jakob Unterwurzacher a7d59032d3 syscallcompat: rework Fchmodat to FchmodatNofollow
We never want Fchmodat to follow symlinks, so follow what
Qemu does, and call our function FchmodatNofollow.
2019-01-14 21:54:16 +01:00
Jakob Unterwurzacher e885f08746 fusefrontend: drop last remaining call into loopbackFileSystem
The only call forwarded to loopbackFileSystem was Statfs,
which is trivial to implement.

Implement it and drop loopbackFileSystem, as having it carries the
risk that a coding error bypasses the usual encryption/decryption
chain.
2019-01-13 20:27:35 +01:00
Sebastian Lackner d44fe89ba4 fusefrontend: Do not pass unsupported flags to Faccessat on macOS.
Fixes mounting of forward mounts on macOS High Sierra.
2019-01-13 14:10:34 +01:00
Sebastian Lackner 99e8b6d288 fusefrontend: Preserve SUID/SGID/sticky-bits in openWriteOnlyFile and Rmdir.
Fixes https://github.com/rfjakob/gocryptfs/issues/336 and
https://github.com/rfjakob/gocryptfs/issues/337.
2019-01-12 21:24:50 +01:00
Sebastian Lackner efc280330c fusefrontend: -allow_other: Use SymlinkatUser in Symlink FUSE call.
Instead of manually adjusting the user after creating the symlink,
adjust effective permissions and let the kernel deal with it.

Related to https://github.com/rfjakob/gocryptfs/issues/338.
2019-01-12 21:22:58 +01:00
Sebastian Lackner 1fbe7798cf fusefrontend: -allow_other: Use MknodatUser in Mknod FUSE call.
Instead of manually adjusting the user and mode after creating the
device file, adjust effective permissions and let the kernel deal
with it.

Related to https://github.com/rfjakob/gocryptfs/issues/338.
2019-01-12 21:20:16 +01:00
Sebastian Lackner 03b9d65cce fusefrontend: -allow_other: Use OpenatUser in Create FUSE call.
Revert commit b22cc03c75.

Instead of manually adjusting the user and mode after creating the
file, adjust effective permissions and let the kernel deal with it.

Related to https://github.com/rfjakob/gocryptfs/issues/338.
2019-01-12 20:54:39 +01:00
Sebastian Lackner 669322482a fusefrontend: Don't chown gocryptfs.diriv files.
The current code has a risk of race-conditions, since we pass a path
containing "/" to Fchownat. We could fix this by opening a file descriptor,
however, this does not seem worth the effort. We also don't chown *.name files.
2019-01-12 20:35:50 +01:00
Jakob Unterwurzacher b22cc03c75 fusefrontend: -allow_other: set file mode *after* chown in Create()
Reported by @slackner at https://github.com/rfjakob/gocryptfs/issues/327 :

Possible race-conditions between file creation and Fchownat

* Assume a system contains a gocryptfs mount as root user
  with -allow_other
* As a regular user create a new file with mode containing
  the SUID flag and write access for other users
* Before gocryptfs executes the Fchownat call, try to open
  the file again, write some exploit code to it, and try to run it.

For a short time, the file is owned by root and has the SUID flag, so
this is pretty dangerous.
2019-01-08 21:50:10 +01:00
Sebastian Lackner 57a52d6aef fusefrontend: Clarify access mode check related to O_WRONLY handling.
Use O_ACCMODE mask in openWriteOnlyFile for improved readability.
2019-01-07 21:25:23 +01:00
Sebastian Lackner 2332462e78 fusefrontend: Filter O_CREAT in mangleOpenFlags. 2019-01-07 21:19:13 +01:00
Sebastian Lackner aa2fa24c42 fusefrontend: Check result of Fchmod syscall.
Fixes https://github.com/rfjakob/gocryptfs/issues/328
2019-01-06 21:00:17 +01:00
Jakob Unterwurzacher 3473a84963 fusefrontend: print warning when Create() runs out of file descriptors
We alread have this warning in Open(), but xfstests generic/488
causes "too many open files" via Create. Add the same message so
the user sees what is going on.
2019-01-04 23:15:04 +01:00
Sebastian Lackner ab169443fd A few more spelling fixes.
Found with the 'codespell' utility.
2019-01-04 01:23:44 +01:00
Jakob Unterwurzacher 4f66d66755 fusefrontend: add dirCache 2019-01-03 15:31:13 +01:00
Jakob Unterwurzacher 352f3147c5 fusefrontend: move openBackingDir into its own file
This function is in all fastpaths, will get a cache, and needs
its own file.
renamed:    internal/fusefrontend/names.go -> internal/fusefrontend/openbackingdir.go
renamed:    internal/fusefrontend/names_test.go -> internal/fusefrontend/openbackingdir_test.go
2019-01-02 21:52:52 +01:00
Jakob Unterwurzacher b214be5e3f fusefrontend: xattr: fix operations on files without read permissions
* listxattr is fixed via the /proc/self/fd trick
* setxattr,removexattr are fixed by opening the file O_WRONLY

Fixes https://github.com/rfjakob/gocryptfs/issues/308
2019-01-02 20:48:46 +01:00
Jakob Unterwurzacher bb7f919674 fusefrontend: don't downgrade type needlessly 2019-01-02 20:45:08 +01:00
Jakob Unterwurzacher 77c3df48ef fusefrontend: fix fd leak in Access()
Thanks @slackner!

Fixes https://github.com/rfjakob/gocryptfs/issues/306
2019-01-01 20:10:17 +01:00
Jakob Unterwurzacher a355670ca2 fusefrontend: make Utimens symlink-safe
unix.UtimesNanoAt now also exists on Darwin, yay!
2019-01-01 16:24:25 +01:00
Jakob Unterwurzacher d4b7f42c3b fusefrontend: mark Truncate, Unlink, Symlink symlink-safe
No changes needed.
2019-01-01 16:24:25 +01:00
Jakob Unterwurzacher 436f918c21 fusefrontend: make Rmdir symlink-safe
Now uses Unlinkat.
2019-01-01 16:24:25 +01:00
Jakob Unterwurzacher 2de3851abd nametransform: rename WriteLongName() -> WriteLongNameAt()
And also rename DeleteLongName() -> DeleteLongNameAt(). The
naming follow the names open the openat() etc syscalls.
2019-01-01 16:24:25 +01:00
Jakob Unterwurzacher 4fae240153 fusefrontend: make Readlink() symlink-safe
Now symlink-safe through Readlinkat().
2019-01-01 16:24:25 +01:00
Jakob Unterwurzacher 0c1ceed1fa fusefrontend: make GetAttr() symlink-safe
Use openBackingDir() and Fstatat().

High performance impact, though part of it should be
mitigated by adding DirIV caching to the new code paths.

$ ./benchmark.bash
Testing gocryptfs at /tmp/benchmark.bash.Eou: gocryptfs v1.6-37-ge3914b3-dirty; go-fuse v20170619-66-g6df8ddc; 2018-10-14 go1.11
WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.2289 s, 213 MB/s
READ:  262144000 bytes (262 MB, 250 MiB) copied, 1.02616 s, 255 MB/s
UNTAR: 24.490
MD5:   13.120
LS:    3.368
RM:    9.232
2019-01-01 16:24:09 +01:00
Jakob Unterwurzacher 0e2e7c13cf fusefrontend: mark symlink-safe FUSE calls
Document which FUSE calls are already symlink-safe in
the function comment.
2019-01-01 16:24:09 +01:00
Jakob Unterwurzacher ed6ed513d7 fusefrontend: make Access() symlink-safe.
Make Access() symlink-safe through use of faccessat.
2019-01-01 16:24:09 +01:00
Jesse Dunietz 87d3ed9187 Add option for autounmount
Even though filesystem notifications aren't implemented for FUSE, I decided to
try my hand at implementing the autounmount feature (#128). I based it on the
EncFS autounmount code, which records filesystem accesses and checks every X
seconds whether it's idled long enough to unmount.

I've tested the feature locally, but I haven't added any tests for this flag.
I also haven't worked with Go before. So please let me know if there's
anything that should be done differently.

One particular concern: I worked from the assumption that the open files table
is unique per-filesystem. If that's not true, I'll need to add an open file
count and associated lock to the Filesystem type instead.

https://github.com/rfjakob/gocryptfs/pull/265
2018-10-11 20:16:45 +02:00
Jakob Unterwurzacher e4f1a32a9a fusefrontend: Fix uint16 build failure on Darwin
Error was:

  # github.com/rfjakob/gocryptfs/internal/fusefrontend
  internal/fusefrontend/fs.go:179: cannot use perms | 256 (type uint16) as type uint32 in argument to syscall.Fchmod
  internal/fusefrontend/fs.go:185: cannot use perms (type uint16) as type uint32 in argument to syscall.Fchmod
2018-09-23 12:17:59 +02:00
Jakob Unterwurzacher a1fb456618 fusefrontend: make Rename() symlink-safe
Use Openat() and the openBackingDir() helper so we
never follow symlinks.
2018-09-23 12:17:59 +02:00
Jakob Unterwurzacher 897bb8924f fusefrontend: make Create() symlink-safe
Use Openat() and the openBackingDir() helper so we
never follow symlinks.
2018-09-23 12:17:59 +02:00
Jakob Unterwurzacher 63762b33af fusefrontend: Open(): fix dirfd leak
Close was missing.
2018-09-23 12:17:59 +02:00
Jakob Unterwurzacher c270b21efc fusefrontend: get rid of os.File* wrapping
Directly use int file descriptors for the dirfd
and get rid of one level of indirection.
2018-09-23 12:17:26 +02:00
Jakob Unterwurzacher 22fba4ac3e fusefrontent: make Open() symlink-safe 2018-09-23 12:17:26 +02:00
Jakob Unterwurzacher e8d8ae54d3 fusefrontend: use OpenDirNofollow in openBackingDir
Rename openBackingPath to openBackingDir and use OpenDirNofollow
to be safe against symlink races. Note that openBackingDir is
not used in several important code paths like Create().

But it is used in Unlink, and the performance impact in the RM benchmark
to be acceptable:

Before

	$ ./benchmark.bash
	Testing gocryptfs at /tmp/benchmark.bash.bYO: gocryptfs v1.6-12-g930c37e-dirty; go-fuse v20170619-49-gb11e293; 2018-09-08 go1.10.3
	WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.07979 s, 243 MB/s
	READ:  262144000 bytes (262 MB, 250 MiB) copied, 0.882413 s, 297 MB/s
	UNTAR: 16.703
	MD5:   7.606
	LS:    1.349
	RM:    3.237

After

	$ ./benchmark.bash
	Testing gocryptfs at /tmp/benchmark.bash.jK3: gocryptfs v1.6-13-g84d6faf-dirty; go-fuse v20170619-49-gb11e293; 2018-09-08 go1.10.3
	WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.06261 s, 247 MB/s
	READ:  262144000 bytes (262 MB, 250 MiB) copied, 0.947228 s, 277 MB/s
	UNTAR: 17.197
	MD5:   7.540
	LS:    1.364
	RM:    3.410
2018-09-08 19:27:33 +02:00
Jakob Unterwurzacher ec2fdc19cf reverse mode: add --exclude option
https://github.com/rfjakob/gocryptfs/issues/235
2018-08-11 23:26:49 +02:00
Jakob Unterwurzacher 53f7e1a0f0 macos: fix O_DIRECT build failure
O_DIRECT has no direct equivalent on MacOS
(check out https://github.com/libuv/libuv/issues/1600 for details).

Just define it to zero there.
2018-07-04 09:04:00 +02:00
Jakob Unterwurzacher 893e41149e fusefrontend: disallow O_DIRECT and fall back to buffered IO
O_DIRECT accesses must be aligned in both offset and length. Due to our
crypto header, alignment will be off, even if userspace makes aligned
accesses. Running xfstests generic/013 on ext4 used to trigger lots of
EINVAL errors due to missing alignment. Just fall back to buffered IO.
2018-07-02 23:54:37 +02:00