diff options
author | Jakob Unterwurzacher | 2018-09-22 20:31:49 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2018-09-23 12:17:59 +0200 |
commit | 897bb8924fe23be5c989b519b62fbf7841a31a4c (patch) | |
tree | cd8f2f6f1ac382ba15c29ac8b49ad51a06331e88 | |
parent | 63762b33afd387ee45d40dec6f42653bd4dd5f98 (diff) |
fusefrontend: make Create() symlink-safe
Use Openat() and the openBackingDir() helper so we
never follow symlinks.
-rw-r--r-- | internal/fusefrontend/fs.go | 34 |
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. |