e8d8ae54d3
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
72 lines
2.2 KiB
Go
72 lines
2.2 KiB
Go
package fusefrontend
|
|
|
|
// This file forwards file encryption operations to cryptfs
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/rfjakob/gocryptfs/internal/configfile"
|
|
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
|
)
|
|
|
|
// isFiltered - check if plaintext "path" should be forbidden
|
|
//
|
|
// Prevents name clashes with internal files when file names are not encrypted
|
|
func (fs *FS) isFiltered(path string) bool {
|
|
if !fs.args.PlaintextNames {
|
|
return false
|
|
}
|
|
// gocryptfs.conf in the root directory is forbidden
|
|
if path == configfile.ConfDefaultName {
|
|
tlog.Info.Printf("The name /%s is reserved when -plaintextnames is used\n",
|
|
configfile.ConfDefaultName)
|
|
return true
|
|
}
|
|
// Note: gocryptfs.diriv is NOT forbidden because diriv and plaintextnames
|
|
// are exclusive
|
|
return false
|
|
}
|
|
|
|
// GetBackingPath - get the absolute encrypted path of the backing file
|
|
// from the relative plaintext path "relPath"
|
|
func (fs *FS) getBackingPath(relPath string) (string, error) {
|
|
cPath, err := fs.encryptPath(relPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
cAbsPath := filepath.Join(fs.args.Cipherdir, cPath)
|
|
tlog.Debug.Printf("getBackingPath: %s + %s -> %s", fs.args.Cipherdir, relPath, cAbsPath)
|
|
return cAbsPath, nil
|
|
}
|
|
|
|
// openBackingDir opens the parent ciphertext directory of plaintext path
|
|
// "relPath" and returns the dirfd and the encrypted basename.
|
|
// The caller should then use Openat(dirfd, cName, ...) and friends.
|
|
// openBackingDir is secure against symlink races.
|
|
func (fs *FS) openBackingDir(relPath string) (*os.File, string, error) {
|
|
cRelPath, err := fs.encryptPath(relPath)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
// Open parent dir
|
|
dirfd, err := syscallcompat.OpenDirNofollow(fs.args.Cipherdir, filepath.Dir(cRelPath))
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
return os.NewFile(uintptr(dirfd), cRelPath), filepath.Base(cRelPath), nil
|
|
}
|
|
|
|
// encryptPath - encrypt relative plaintext path
|
|
func (fs *FS) encryptPath(plainPath string) (string, error) {
|
|
if fs.args.PlaintextNames {
|
|
return plainPath, nil
|
|
}
|
|
fs.dirIVLock.RLock()
|
|
cPath, err := fs.nameTransform.EncryptPathDirIV(plainPath, fs.args.Cipherdir)
|
|
tlog.Debug.Printf("encryptPath '%s' -> '%s' (err: %v)", plainPath, cPath, err)
|
|
fs.dirIVLock.RUnlock()
|
|
return cPath, err
|
|
}
|