aboutsummaryrefslogtreecommitdiff
path: root/internal
AgeCommit message (Collapse)Author
2017-11-29fusefrontend: allow_other: close race between mkdir and chownSebastian Lackner
Fixes the same problem as described in 72b975867a3b9bdf53fc2da62e2ba4a328d7e4ab, except for directories instead of device nodes.
2017-11-29fusefrontend: Use Fchownat to implement ChownSebastian Lackner
2017-11-29fusefrontend: Use Fchmodat to implement ChmodSebastian Lackner
2017-11-29syscallcompat: Introduce unlinkat syscall with flags argumentSebastian Lackner
2017-11-28fusefrontend: Use openBackingPath in Unlink and simplify codeSebastian Lackner
2017-11-28fusefrontend: Handle PlaintextNames mode in UnlinkSebastian Lackner
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-28fusefrontend: Introduce a openBackingPath helper and use it to simplify ↵Sebastian Lackner
Mknod and Symlink
2017-11-28fusefrontend: allow_other: close race between symlink and chownSebastian Lackner
Fixes the same problem as described in 72b975867a3b9bdf53fc2da62e2ba4a328d7e4ab, except for symlinks instead of device nodes.
2017-11-28fusefrontend: Use the Symlinkat syscall for longname handlingSebastian Lackner
2017-11-28fusefrontend: Set owner after symlink creation in PlaintextNames modeSebastian Lackner
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-28fusefrontend: Handle PlaintextNames mode in MknodSebastian Lackner
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-28syscallcompat: Fix Fchownat syscall wrapper on darwinSebastian Lackner
* Acquire the lock before reading the current directory * Fix a file descriptor leak
2017-11-27fusefronted: allow_other: close race between mknod and chownJakob Unterwurzacher
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-26reverse: reject too-long symlink target reads with ENAMETOOLONGJakob Unterwurzacher
If the symlink target gets too long due to base64 encoding, we should return ENAMETOOLONG instead of having the kernel reject the data and returning an I/O error to the user. Fixes https://github.com/rfjakob/gocryptfs/issues/167
2017-11-25fusefrontend_reverse: Do not mix up cache information for different directoriesSebastian Lackner
Fixes https://github.com/rfjakob/gocryptfs/issues/168 Steps to reproduce the problem: * Create a regular reverse mount point * Create files with the same very long name in multiple directories - so far everything works as expected, and it will appear with a different name each time, for example, gocryptfs.longname.A in directory A and gocryptfs.longname.B in directory B * Try to access a path with A/gocryptfs.longname.B or B/gocryptfs.longname.A - this should fail, but it actually works. The problem is that the longname cache only uses the path as key and not the dir or divIV. Assume an attacker can directly interact with a reverse mount and knows the relation longname path -> unencoded path in one directory, it allows to test if the same unencoded filename appears in any other directory.
2017-11-25fusefrontend: Skip gocryptfs.diriv handling when directory was deleted ↵Sebastian Lackner
successfully Fixes https://github.com/rfjakob/gocryptfs/issues/171 Steps to reproduce: * Create a regular forward mount point * Create a new directory in the mount point * Manually delete the gocryptfs.diriv file from the corresponding ciphertext directory * Attempt to delete the directory with 'rmdir <dirname>' Although the code explicitly checks for empty directories, it will still attempt to move the non-existent gocryptfs.diriv file and fails with: rmdir: failed to remove '<dirname>': No such file or directory
2017-11-25fusefrontend: Fix longname handling for renames with existing targetSebastian Lackner
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-22fusefrontend_reverse: Add a missing Close() callSebastian Lackner
2017-11-22nametransform: Return error if decrypted name is '.' or '..'Sebastian Lackner
2017-11-21main: Add '-devrandom' commandline optionSebastian Lackner
Allows to use /dev/random for generating the master key instead of the default Go implementation. When the kernel random generator has been properly initialized both are considered equally secure, however: * Versions of Go prior to 1.9 just fall back to /dev/urandom if the getrandom() syscall would be blocking (Go Bug #19274) * Kernel versions prior to 3.17 do not support getrandom(), and there is no check if the random generator has been properly initialized before reading from /dev/urandom This is especially useful for embedded hardware with low-entroy. Please note that generation of the master key might block indefinitely if the kernel cannot harvest enough entropy.
2017-10-22tests: don't read /proc, the number of entries changes too quicklyJakob Unterwurzacher
This could lead to test failures like this: --- FAIL: TestGetdents (0.02s) getdents_test.go:57: len(getdentsEntries)=362, len(readdirEntries)=360 FAIL
2017-10-21Revert most of "fusefrontend: clamp oversized reads"Jakob Unterwurzacher
We cannot return less data than requested to the kernel! From https://libfuse.github.io/doxygen/structfuse__operations.html: Read should return exactly the number of bytes requested except on EOF or error, otherwise the rest of the data will be substituted with zeroes. Reverts commit 3009ec9852316c3c696f77f476390ab5a6d8d6d7 minus the formatting improvements we want to keep. Fixes https://github.com/rfjakob/gocryptfs/issues/147 Reopens https://github.com/rfjakob/gocryptfs/issues/145
2017-10-19contentenc: reserve one additional block in CReqPoolJakob Unterwurzacher
...to account for unaligned reads. I have not seen this happen in the wild because the kernel always seems to issue 4k-aligned requests. But the cost of the additional block in the pool is low and prevents a buffer overrun panic when an unaligned read does happen.
2017-10-17fusefrontend: clamp oversized readsJakob Unterwurzacher
Our byte cache pools are sized acc. to MAX_KERNEL_WRITE, but the running kernel may have a higher limit set. Clamp to what we can handle. Fixes a panic on a Synology NAS reported at https://github.com/rfjakob/gocryptfs/issues/145
2017-10-01fusefrontend_reverse: fix 176-byte namesJakob Unterwurzacher
A file with a name of exactly 176 bytes length caused this error: ls: cannot access ./tmp/dsg/sXSGJLTuZuW1FarwIkJs0w/b6mGjdxIRpaeanTo0rbh0A/QjMRrQZC_4WLhmHI1UOBcA/gocryptfs.longname.QV-UipdDXeUVdl05WruoEzBNPrQCfpu6OzJL0_QnDKY: No such file or directory ls: cannot access ./tmp/dsg/sXSGJLTuZuW1FarwIkJs0w/b6mGjdxIRpaeanTo0rbh0A/QjMRrQZC_4WLhmHI1UOBcA/gocryptfs.longname.QV-UipdDXeUVdl05WruoEzBNPrQCfpu6OzJL0_QnDKY.name: No such file or directory -????????? ? ? ? ? ? gocryptfs.longname.QV-UipdDXeUVdl05WruoEzBNPrQCfpu6OzJL0_QnDKY -????????? ? ? ? ? ? gocryptfs.longname.QV-UipdDXeUVdl05WruoEzBNPrQCfpu6OzJL0_QnDKY.name Root cause was a wrong shortNameMax constant that failed to account for the obligatory padding byte. Fix the constant and also expand the TestLongnameStat test case to test ALL file name lengths from 1-255 bytes. Fixes https://github.com/rfjakob/gocryptfs/issues/143 .
2017-09-17siv_aead: fix trivial typo in commentJakob Unterwurzacher
2017-09-17contentenc: deduplicate AD packing into new concatAD() funcJakob Unterwurzacher
The encrypt and decrypt path both had a copy that were equivalent but ordered differently, which was confusing. Consolidate it in a new dedicated function.
2017-09-17contentenc: DecryptBlocks: give block number counter a clearer nameJakob Unterwurzacher
Using firstBlockNo as the counter is confusing, create a copy named "blockNo" and use that.
2017-09-05macos: automatically remove .DS_Store on RmdirJakob Unterwurzacher
MacOS sprinkles .DS_Store files everywhere. This is hard to avoid for users, so handle it transparently in Rmdir(). Mitigates https://github.com/rfjakob/gocryptfs/issues/140
2017-09-05fusefrontend: reorder logic in Rmdir to get rid of one indentation levelJakob Unterwurzacher
Handle the errors first so that the normal code path is not indented. This should not cause any behavoir changes.
2017-09-05macos: don't throw IO errors because of .DS_Store filesJakob Unterwurzacher
MacOS creates lots of these files, and if the directory is otherwise empty, we would throw an IO error to the unsuspecting user. With this patch, we log a warning, but otherwise pretend we did not see it. Mitigates https://github.com/rfjakob/gocryptfs/issues/140
2017-09-03syscallcompat: Getdents: warn once if we get DT_UNKNOWNJakob Unterwurzacher
...and if Getdents is not available at all. Due to this warning I now know that SSHFS always returns DT_UNKNOWN: gocryptfs[8129]: Getdents: convertDType: received DT_UNKNOWN, falling back to Lstat This behavoir is confirmed at http://ahefner.livejournal.com/16875.html: "With sshfs, I finally found that obscure case. The dtype is always set to DT_UNKNOWN [...]"
2017-09-03fusefrontend: use DirIVCache in OpenDir()Jakob Unterwurzacher
Previously, OpenDir() did not use the cache at all, missing an opportunity to speed up repeated directory reads.
2017-09-03dirivcache: add better function comments + a sanity check on Store()Jakob Unterwurzacher
The comments were unclear on whether relative or absolute paths have to be passed.
2017-08-21Fix misspellings reported by goreportcard.comJakob Unterwurzacher
https://goreportcard.com/report/github.com/rfjakob/gocryptfs#misspell
2017-08-16cryptocore: add urandom + randprefetch benchmarksJakob Unterwurzacher
The benchmark that supported the decision for 512-byte prefetching previously lived outside the repo. Let's add it where it belongs so it cannot get lost.
2017-08-15fusefrontend: use Getdents if availableJakob Unterwurzacher
Getdents avoids calling Lstat on each file.
2017-08-15syscallcompat: implement Getdents()Jakob Unterwurzacher
The Readdir function provided by os is inherently slow because it calls Lstat on all files. Getdents gives us all the information we need, but does not have a proper wrapper in the stdlib. Implement the "Getdents()" wrapper function that calls syscall.Getdents() and parses the returned byte blob to a fuse.DirEntry slice.
2017-08-11main: purge masterkey from memory as soon as possibleJakob Unterwurzacher
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-09nametransform: extend diriv cache to 100 entriesJakob Unterwurzacher
* 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-06nametransform: add Dir() functionJakob Unterwurzacher
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-06nametransform: move diriv cache into it's own packageJakob Unterwurzacher
Needs some space to grow. renamed: internal/nametransform/diriv_cache.go -> internal/nametransform/dirivcache/dirivcache.go
2017-08-06nametransform: deduplicate code to encryptAndHashName()Jakob Unterwurzacher
This operation has been done three time by identical sections of code. Create a function for it.
2017-07-29fusefronted_reverse: fix ino collision between .name and .diriv filesJakob Unterwurzacher
A directory with a long name has two associated virtual files: the .name file and the .diriv files. These used to get the same inode number: $ ls -di1 * */* 33313535 gocryptfs.longname.2togDFouca9mrTwtfF1RNW5DZRAQY8alaR7wO_Xd5Zw 1000000000033313535 gocryptfs.longname.2togDFouca9mrTwtfF1RNW5DZRAQY8alaR7wO_Xd5Zw/gocryptfs.diriv 1000000000033313535 gocryptfs.longname.2togDFouca9mrTwtfF1RNW5DZRAQY8alaR7wO_Xd5Zw.name With this change we use another prefix (2 instead of 1) for .name files. $ ls -di1 * */* 33313535 gocryptfs.longname.2togDFouca9mrTwtfF1RNW5DZRAQY8alaR7wO_Xd5Zw 1000000000033313535 gocryptfs.longname.2togDFouca9mrTwtfF1RNW5DZRAQY8alaR7wO_Xd5Zw/gocryptfs.diriv 2000000000033313535 gocryptfs.longname.2togDFouca9mrTwtfF1RNW5DZRAQY8alaR7wO_Xd5Zw.name
2017-07-27fusefrontend_reverse: return ENOENT for undecryptable namesJakob Unterwurzacher
This was working until DecryptName switched to returning EBADMSG instead of EINVAL. Add a test to catch the regression next time.
2017-07-14macos: make testing without openssl work properlyJakob Unterwurzacher
On MacOS, building and testing without openssl is much easier. The tests should skip tests that fail because of missing openssl instead of aborting. Fixes https://github.com/rfjakob/gocryptfs/issues/123
2017-07-14stupidgcm: fix openssl 1.1 build failureJakob Unterwurzacher
Fixed by including the correct header. Should work on older openssl versions as well. Error was: locking.go:21: undefined reference to `CRYPTO_set_locking_callback'
2017-07-11fusefronted: enable writing to write-only filesJakob Unterwurzacher
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-02contentenc: MergeBlocks: short-circuit the trivial caseJakob Unterwurzacher
Saves 3% for the tar extract benchmark because we skip the allocation.
2017-07-02fusefrontend: doRead: skip decryption for an empty readJakob Unterwurzacher
Previously we ran through the decryption steps even for an empty ciphertext slice. The functions handle it correctly, but returning early skips all the extra calls. Speeds up the tar extract benchmark by about 4%.