summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2018-09-22 20:31:49 +0200
committerJakob Unterwurzacher2018-09-23 12:17:59 +0200
commit897bb8924fe23be5c989b519b62fbf7841a31a4c (patch)
treecd8f2f6f1ac382ba15c29ac8b49ad51a06331e88
parent63762b33afd387ee45d40dec6f42653bd4dd5f98 (diff)
fusefrontend: make Create() symlink-safe
Use Openat() and the openBackingDir() helper so we never follow symlinks.
-rw-r--r--internal/fusefrontend/fs.go34
1 files changed, 12 insertions, 22 deletions
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index d1f031a..a1ccbba 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -196,57 +196,47 @@ func (fs *FS) openWriteOnlyFile(dirfd int, cName string, newFlags int) (fuseFile
}
// Create implements pathfs.Filesystem.
-func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Context) (fuseFile nodefs.File, code fuse.Status) {
+func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Context) (nodefs.File, fuse.Status) {
if fs.isFiltered(path) {
return nil, fuse.EPERM
}
newFlags := fs.mangleOpenFlags(flags)
- cPath, err := fs.getBackingPath(path)
+ dirfd, cName, err := fs.openBackingDir(path)
if err != nil {
return nil, fuse.ToStatus(err)
}
-
- var fd *os.File
- cName := filepath.Base(cPath)
-
+ defer syscall.Close(dirfd)
+ fd := -1
// Handle long file name
if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) {
- var dirfd int
- dirfd, err = syscall.Open(filepath.Dir(cPath), syscall.O_RDONLY|syscall.O_DIRECTORY, 0)
- if err != nil {
- return nil, fuse.ToStatus(err)
- }
- defer syscall.Close(dirfd)
-
// Create ".name"
err = fs.nameTransform.WriteLongName(dirfd, cName, path)
if err != nil {
return nil, fuse.ToStatus(err)
}
-
// Create content
- var fdRaw int
- fdRaw, err = syscallcompat.Openat(dirfd, cName, newFlags|os.O_CREATE|os.O_EXCL, mode)
+ fd, err = syscallcompat.Openat(dirfd, cName, newFlags|os.O_CREATE|os.O_EXCL, mode)
if err != nil {
nametransform.DeleteLongName(dirfd, cName)
return nil, fuse.ToStatus(err)
}
- fd = os.NewFile(uintptr(fdRaw), cName)
+
} else {
- // Normal (short) file name
- fd, err = os.OpenFile(cPath, newFlags|os.O_CREATE|os.O_EXCL, os.FileMode(mode))
+ // Create content, normal (short) file name
+ fd, err = syscallcompat.Openat(dirfd, cName, newFlags|syscall.O_CREAT|syscall.O_EXCL, mode)
if err != nil {
return nil, fuse.ToStatus(err)
}
}
// Set owner
if fs.args.PreserveOwner {
- err = fd.Chown(int(context.Owner.Uid), int(context.Owner.Gid))
+ err = syscall.Fchown(fd, int(context.Owner.Uid), int(context.Owner.Gid))
if err != nil {
- tlog.Warn.Printf("Create: fd.Chown failed: %v", err)
+ tlog.Warn.Printf("Create: Fchown() failed: %v", err)
}
}
- return NewFile(fd, fs)
+ f := os.NewFile(uintptr(fd), cName)
+ return NewFile(f, fs)
}
// Chmod implements pathfs.Filesystem.