Commit Graph

90 Commits

Author SHA1 Message Date
Jakob Unterwurzacher
04858ddd22 nametransform: check name validity on encryption
xfstests generic/523 discovered that we allowed to set
xattrs with "/" in the name, but did not allow to read
them later.

With this change we do not allow to set them in the first
place.
2021-06-02 14:29:48 +02:00
Jakob Unterwurzacher
bed60101f4 nametransform: make gocryptfs.diriv and gocryptfs.xxx.name files world-readable
Make `gocryptfs.diriv` and `gocryptfs.xxx.name` files world-readable to make encrypted backups easier
when mounting via fstab.

Having the files follow chmod/chown of their parent does not seem
to be worth the hassle. The content of the diriv files is not
secret, and both diriv and name files are protected by the
perms of the parent dir.

Fixes https://github.com/rfjakob/gocryptfs/issues/539
2021-01-10 08:07:10 +01:00
Jakob Unterwurzacher
f3394ae286 nametransform: move permission constants to perms.go
Prep for https://github.com/rfjakob/gocryptfs/issues/539
2021-01-10 07:27:04 +01:00
Jakob Unterwurzacher
af4c1fb7a3 syscallcompat: retry ops on EINTR
Retry operations that have been shown to throw EINTR
errors on CIFS.

Todo: Solution for this pain in the back:

	warning: unix.Getdents returned errno 2 in the middle of data
	rm: cannot remove 'linux-3.0.old3/Documentation/ABI/removed': Input/output error

Progress towards fixing https://github.com/rfjakob/gocryptfs/issues/483 .
2020-10-14 00:35:16 +02:00
Jakob Unterwurzacher
84ed139cd2 v2api/reverse: implement Lookup for longname 2020-08-02 19:33:12 +02:00
Jakob Unterwurzacher
261cf12829 badname: stop trying to decrypt at length 22
At least 16 bytes due to AES --> at least 22 characters in base64
2020-06-06 12:49:45 +02:00
DerDonut
a8230d271f Added auto decryption of invalid file names
Changed invalid file decoding and decryption. Function
DecryptName now shortens the filename until the filename is
decodable and decryptable. Will work with valid **and**
invalid Base64URL delimiter (valid delimiter [0-9a-zA-z_\\-].
If the filename is not decryptable at all, it returns the
original cipher name with flag suffix Changed cli tests to
generate decryptable and undecryptable file names with correct
encrypted content. Replacing #474, extends #393
2020-06-06 12:20:31 +02:00
Jakob Unterwurzacher
ead7008a08 Fix spelling mistakes found by misspell
https://github.com/client9/misspell
2020-05-10 00:25:49 +02:00
Jakob Unterwurzacher
f6b1c680b3 nametransform: update comment & simplify tests
The comment still mentioned CBC, which has been removed
a long time ago.

The test definition can be rewritten using slice literals,
saving sume stuttering.
2020-04-18 16:14:48 +02:00
orcas
9ec042f2f6 Show undecryptable filenames if they match supplied glob
Resolves https://github.com/rfjakob/gocryptfs/issues/393
2020-02-28 22:17:59 +01:00
Jakob Unterwurzacher
ec17445b99 forward mode: create gocryptfs.diriv files with 0440 permissions
Makes it easier to share an encrypted folder via a network drive.

https://github.com/rfjakob/gocryptfs/issues/387
2019-03-30 20:06:40 +01: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
19cb6d046a nametransform: reject names longer than 255 chars
Looks like we allowed creating longer names by accident.
Fix that, and add a test that verifies it.
2019-02-17 17:05:05 +01:00
Sebastian Lackner
aae45b4d77 nametransform: Create *.name files with 0400 permission.
Similar to gocryptfs.iv files they are never modified.
2019-01-09 20:42:18 +01:00
Jakob Unterwurzacher
8074f12beb nametransform: ReadDirIVAt: return raw syscall error
Otherwise this can happen, as triggered by xfstests generic/011:

  go-fuse: can't convert error type: openat failed: too many open files

The app then gets a misleading "Function not implemented" error.
2019-01-04 23:21:27 +01:00
Sebastian Lackner
ab169443fd A few more spelling fixes.
Found with the 'codespell' utility.
2019-01-04 01:23:44 +01:00
Sebastian Lackner
61241b0588 nametransform: Add implicit syscall.O_RDONLY flag. 2019-01-03 18:24:05 +01:00
Jakob Unterwurzacher
4f66d66755 fusefrontend: add dirCache 2019-01-03 15:31:13 +01:00
Jakob Unterwurzacher
f6dad8d0fa nametransform: simplify WriteDirIV to WriteDirIVAt
Un-spaghettify the function and let the callers open
the directory.
2019-01-03 15:31:13 +01:00
Jakob Unterwurzacher
2b12bba274 fusefronted: make EncryptPath symlink-safe
Finally allows us to delete EncryptPathDirIV.
2019-01-02 21:45:40 +01:00
Jakob Unterwurzacher
d99a0480f7 nametransform: fix possible incomplete read in ReadLongNameAt
Pread() needs retry logic, so instead of implementing it ourselves,
use os.File.

Reported by @slackner at
c09bf1f228 (r31813394)
2019-01-02 00:09:17 +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
21f1f858b9 fusefrontend: make OpenDir() symlink-safe
Interestingly, little or no performance impact:

$ ./benchmark.bash
Testing gocryptfs at /tmp/benchmark.bash.39W: gocryptfs v1.6-42-g30c2349-dirty; go-fuse v20170619-66-g6df8ddc; 2018-11-04 go1.11
Downloading linux-3.0.tar.gz
/tmp/linux-3.0.tar.gz                  100%[=========================================================================>]  92.20M  2.93MB/s    in 31s
2018-11-04 21:44:44 URL:https://cdn.kernel.org/pub/linux/kernel/v3.0/linux-3.0.tar.gz [96675825/96675825] -> "/tmp/linux-3.0.tar.gz" [1]
WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.1808 s, 222 MB/s
READ:  262144000 bytes (262 MB, 250 MiB) copied, 0.866438 s, 303 MB/s
UNTAR: 24.745
MD5:   12.050
LS:    3.525
RM:    9.544

Note: kernel has been updated:

$ uname -a
Linux brikett 4.18.16-200.fc28.x86_64 #1 SMP Sat Oct 20 23:53:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
2019-01-01 16:24:25 +01:00
Jakob Unterwurzacher
de3a2c1895 fusefrontend: mark a few more functions as symlink-safe / unsafe 2019-01-01 16:24:25 +01:00
Jakob Unterwurzacher
932efbd459 fusefrontend: make openBackingDir() symlink-safe
openBackingDir() used encryptPath(), which is not symlink-safe
itself. Drop encryptPath() and implement our own directory walk.

Adds three seconds to untar and two seconds to rm:

$ ./benchmark.bash
Testing gocryptfs at /tmp/benchmark.bash.MzG: gocryptfs v1.6-36-g8fb3c2f-dirty; go-fuse v20170619-66-g6df8ddc; 2018-10-14 go1.11
WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.25078 s, 210 MB/s
READ:  262144000 bytes (262 MB, 250 MiB) copied, 1.0318 s, 254 MB/s
UNTAR: 20.941
MD5:   11.568
LS:    1.638
RM:    5.337
2019-01-01 16:24:09 +01:00
Jakob Unterwurzacher
c09bf1f228 fusefrontend: make DecryptPath() symlink-safe
DecryptPath is now symlink-safe through the use of *at()
functions.
2019-01-01 16:24:09 +01:00
Jakob Unterwurzacher
545a03da24 nametransform: comments: directly link to ioutil.WriteFile fix
So the reader does not have to read through the whole ticket.
The commit message has a nice summary of the problem.
2019-01-01 16:23:28 +01:00
Sebastian Lackner
87ced5f95d nametransform: Delete incomplete longname files on error. 2019-01-01 16:09:57 +01:00
Sebastian Lackner
874eaf9734 Assorted spelling fixes.
Mostly detected with the 'codespell' utility, but also includes some
manual grammar fixes.
2018-12-27 15:19:55 +01: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
c70df522d2 fusefrontend: doWrite: delete file header if first write fails
xfstests generic/083 fills the filesystem almost completely while
running fsstress in parallel. In fsck, these would show up:

  readFileID 2580: incomplete file, got 18 instead of 19 bytes

This could happen when writing the file header works, but writing
the actual data fails.

Now we kill the header again by truncating the file to zero.
2018-07-15 15:12:55 +02:00
Jakob Unterwurzacher
bbf5b72fff WriteDirIV: delete incomplete gocryptfs.diriv file if write fails
If the underlying filesystem is full, writing to gocryptfs.diriv may
fail, and later fsck show this:

	OpenDir "xyz": could not read gocryptfs.diriv: wanted 16 bytes, got 0

Uncovered by xfstests generic/083.

Also fixes a fd leak in the error path.
2018-07-15 12:02:39 +02:00
Jakob Unterwurzacher
b6c8960b01 fsck: clean up log output
Make sure we get only 1 warning output per
problem.

Also, add new corruption types to broken_fs_v1.4.
2018-04-02 18:32:30 +02:00
Jakob Unterwurzacher
9f8d0d8e57 gccgo: replace syscall.NAME_MAX with unix.NAME_MAX
For some reason the syscall.NAME_MAX constant does not exist
on gccgo, and it does not hurt us to use unix.NAME_MAX instead.

https://github.com/rfjakob/gocryptfs/issues/201
2018-02-01 23:50:11 +01:00
Sebastian Lackner
9bcde0c09e fusefrontend: Improve documentation of mkdirWithIv and WriteDirIV
As requested in https://github.com/rfjakob/gocryptfs/pull/179
2017-12-01 09:41:52 +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
614745ee57 fusefrontend: allow_other: close race between mkdir and chown
Fixes the same problem as described in 72b975867a,
except for directories instead of device nodes.
2017-11-29 13:28:04 +01:00
Sebastian Lackner
0f44c617d0 syscallcompat: Introduce unlinkat syscall with flags argument 2017-11-29 12:41:23 +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
Sebastian Lackner
c547673529 nametransform: Return error if decrypted name is '.' or '..' 2017-11-22 23:42:08 +01:00
Jakob Unterwurzacher
7da0e97c8b dirivcache: add better function comments + a sanity check on Store()
The comments were unclear on whether relative or absolute paths
have to be passed.
2017-09-03 13:53:50 +02:00
Jakob Unterwurzacher
e80b5f2049 nametransform: extend diriv cache to 100 entries
* extend the diriv cache to 100 entries
* add special handling for the immutable root diriv

The better cache allows to shed some complexity from the path
encryption logic (parent-of-parent check).

Mitigates https://github.com/rfjakob/gocryptfs/issues/127
2017-08-09 22:00:53 +02:00
Jakob Unterwurzacher
75ec94a87a nametransform: add Dir() function
Dir is like filepath.Dir but returns "" instead of ".".
This was already implemented in fusefrontend_reverse as saneDir().

We will need it in nametransform for the improved diriv caching.
2017-08-06 23:14:39 +02:00
Jakob Unterwurzacher
5190cc09bb nametransform: move diriv cache into it's own package
Needs some space to grow.

renamed:    internal/nametransform/diriv_cache.go -> internal/nametransform/dirivcache/dirivcache.go
2017-08-06 21:59:15 +02:00
Jakob Unterwurzacher
32611ff97a nametransform: deduplicate code to encryptAndHashName()
This operation has been done three time by identical
sections of code. Create a function for it.
2017-08-06 21:23:42 +02:00
Jakob Unterwurzacher
9a3f9350fe nametransform: reject all-zero dirIV
This should never happen in normal operation and is a sign of
data corruption. Catch it early.
2017-05-25 14:21:55 +02:00
Jakob Unterwurzacher
e827763f2e nametransform: harden name decryption against invalid input
This fixes a few issues I have found reviewing the code:

1) Limit the amount of data ReadLongName() will read. Previously,
you could send gocryptfs into out-of-memory by symlinking
gocryptfs.diriv to /dev/zero.

2) Handle the empty input case in unPad16() by returning an
error. Previously, it would panic with an out-of-bounds array
read. It is unclear to me if this could actually be triggered.

3) Reject empty names after base64-decoding in DecryptName().
An empty name crashes emeCipher.Decrypt().
It is unclear to me if B64.DecodeString() can actually return
a non-error empty result, but let's guard against it anyway.
2017-05-23 21:26:38 +02:00
Jakob Unterwurzacher
245b84c887 nametransform: diriv cache: fall back to the grandparent
When a user calls into a deep directory hierarchy, we often
get a sequence like this from the kernel:

LOOKUP a
LOOKUP a/b
LOOKUP a/b/c
LOOKUP a/b/c/d

The diriv cache was not effective for this pattern, because it
was designed for this:

LOOKUP a/a
LOOKUP a/b
LOOKUP a/c
LOOKUP a/d

By also using the cached entry of the grandparent we can avoid lots
of diriv reads.

This benchmark is against a large encrypted directory hosted on NFS:

Before:

  $ time ls -R nfs-backed-mount > /dev/null
  real	1m35.976s
  user	0m0.248s
  sys	0m0.281s

After:

  $ time ls -R nfs-backed-mount > /dev/null
  real	1m3.670s
  user	0m0.217s
  sys 	0m0.403s
2017-05-22 22:36:54 +02:00
Jakob Unterwurzacher
26881538e1 nametranform, fusefrontend: better errors on invalid names
nametransform.DecryptName() now always returns syscall.EBADMSG if
the name was invalid.

fusefrontend.OpenDir error messages have been normalized.
2017-05-07 20:58:27 +02:00
Jakob Unterwurzacher
7d38f80a78 nametransform: WriteDirIV: replace ioutil.WriteFile
As reported at https://github.com/rfjakob/gocryptfs/issues/105 ,
the "ioutil.WriteFile(file, iv, 0400)" call causes "permissions denied"
errors on an NFSv4 setup.

"strace"ing diriv creation and gocryptfs.conf creation shows this:

conf (works on the user's NFSv4 mount):
openat(AT_FDCWD, "/tmp/a/gocryptfs.conf.tmp", O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0400) = 3

diriv (fails):
openat(AT_FDCWD, "/tmp/a/gocryptfs.diriv", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0400) = 3

This patch creates the diriv file with the same flags that are used for
creating the conf:
openat(AT_FDCWD, "/tmp/a/gocryptfs.diriv", O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0400) = 3

Closes https://github.com/rfjakob/gocryptfs/issues/105
2017-04-29 14:15:13 +02:00