fusefrontend: make Readlink() symlink-safe
Now symlink-safe through Readlinkat().
This commit is contained in:
parent
21f1f858b9
commit
4fae240153
@ -377,6 +377,8 @@ func (fs *FS) StatFs(path string) *fuse.StatfsOut {
|
||||
// decryptSymlinkTarget: "cData64" is base64-decoded and decrypted
|
||||
// like file contents (GCM).
|
||||
// The empty string decrypts to the empty string.
|
||||
//
|
||||
// This function does not do any I/O and is hence symlink-safe.
|
||||
func (fs *FS) decryptSymlinkTarget(cData64 string) (string, error) {
|
||||
if cData64 == "" {
|
||||
return "", nil
|
||||
@ -392,14 +394,16 @@ func (fs *FS) decryptSymlinkTarget(cData64 string) (string, error) {
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
// Readlink implements pathfs.Filesystem.
|
||||
// Readlink - FUSE call.
|
||||
//
|
||||
// Symlink-safe through openBackingDir() + Readlinkat().
|
||||
func (fs *FS) Readlink(relPath string, context *fuse.Context) (out string, status fuse.Status) {
|
||||
cPath, err := fs.encryptPath(relPath)
|
||||
dirfd, cName, err := fs.openBackingDir(relPath)
|
||||
if err != nil {
|
||||
return "", fuse.ToStatus(err)
|
||||
}
|
||||
cAbsPath := filepath.Join(fs.args.Cipherdir, cPath)
|
||||
cTarget, err := os.Readlink(cAbsPath)
|
||||
defer syscall.Close(dirfd)
|
||||
cTarget, err := syscallcompat.Readlinkat(dirfd, cName)
|
||||
if err != nil {
|
||||
return "", fuse.ToStatus(err)
|
||||
}
|
||||
@ -409,7 +413,7 @@ func (fs *FS) Readlink(relPath string, context *fuse.Context) (out string, statu
|
||||
// Symlinks are encrypted like file contents (GCM) and base64-encoded
|
||||
target, err := fs.decryptSymlinkTarget(cTarget)
|
||||
if err != nil {
|
||||
tlog.Warn.Printf("Readlink %q: decrypting target failed: %v", cPath, err)
|
||||
tlog.Warn.Printf("Readlink %q: decrypting target failed: %v", cName, err)
|
||||
return "", fuse.EIO
|
||||
}
|
||||
return string(target), fuse.OK
|
||||
|
@ -10,10 +10,8 @@ import (
|
||||
// It is not defined on Darwin, so we use the Linux value.
|
||||
const PATH_MAX = 4096
|
||||
|
||||
// Readlinkat exists both in Linux and in MacOS 10.10+. We may add an
|
||||
// emulated version for users on older MacOS versions if there is
|
||||
// demand.
|
||||
// Buffer allocation is handled internally, unlike the bare unix.Readlinkat.
|
||||
// Readlinkat is a convenience wrapper around unix.Readlinkat() that takes
|
||||
// care of buffer sizing. Implemented like os.Readlink().
|
||||
func Readlinkat(dirfd int, path string) (string, error) {
|
||||
// Allocate the buffer exponentially like os.Readlink does.
|
||||
for bufsz := 128; ; bufsz *= 2 {
|
||||
|
Loading…
Reference in New Issue
Block a user