Skip to content

Commit

Permalink
fusefrontend: -allow_other: Use OpenatUser in Create FUSE call.
Browse files Browse the repository at this point in the history
Revert commit b22cc03.

Instead of manually adjusting the user and mode after creating the
file, adjust effective permissions and let the kernel deal with it.

Related to #338.
  • Loading branch information
slackner committed Jan 12, 2019
1 parent 6693224 commit 03b9d65
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 28 deletions.
34 changes: 6 additions & 28 deletions internal/fusefrontend/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,11 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
return nil, fuse.ToStatus(err)
}
defer syscall.Close(dirfd)
// Don't set full mode before we have set the correct owner. Files with SUID/SGID
// mode belonging to the wrong owner would be a security risk. Even for other
// modes, we don't want anyone else to open the file in the meantime: the fd would
// stay open and could later be used to read the file.
origMode := mode
if fs.args.PreserveOwner {
mode = 0000
}
fd := -1
// Make sure context is nil if we don't want to preserve the owner
if !fs.args.PreserveOwner {
context = nil
}
// Handle long file name
if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) {
// Create ".name"
Expand All @@ -255,14 +251,14 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
return nil, fuse.ToStatus(err)
}
// Create content
fd, err = syscallcompat.Openat(dirfd, cName, newFlags|os.O_CREATE|os.O_EXCL, mode)
fd, err = syscallcompat.OpenatUser(dirfd, cName, newFlags|os.O_CREATE|os.O_EXCL, mode, context)
if err != nil {
nametransform.DeleteLongNameAt(dirfd, cName)
return nil, fuse.ToStatus(err)
}
} else {
// Create content, normal (short) file name
fd, err = syscallcompat.Openat(dirfd, cName, newFlags|syscall.O_CREAT|syscall.O_EXCL, mode)
fd, err = syscallcompat.OpenatUser(dirfd, cName, newFlags|syscall.O_CREAT|syscall.O_EXCL, mode, context)
if err != nil {
// xfstests generic/488 triggers this
if err == syscall.EMFILE {
Expand All @@ -273,24 +269,6 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
return nil, fuse.ToStatus(err)
}
}
// Set owner
if fs.args.PreserveOwner {
err = syscall.Fchown(fd, int(context.Owner.Uid), int(context.Owner.Gid))
if err != nil {
tlog.Warn.Printf("Create %q: Fchown %d:%d failed: %v", cName, context.Owner.Uid, context.Owner.Gid, err)
// In case of a failure, we don't want to proceed setting more
// permissive modes.
syscall.Close(fd)
return nil, fuse.ToStatus(err)
}
}
// Set mode
if mode != origMode {
err = syscall.Fchmod(fd, origMode)
if err != nil {
tlog.Warn.Printf("Create %q: Fchmod %#o -> %#o failed: %v", cName, mode, origMode, err)
}
}
f := os.NewFile(uintptr(fd), cName)
return NewFile(f, fs)
}
Expand Down
5 changes: 5 additions & 0 deletions internal/syscallcompat/sys_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
return emulateOpenat(dirfd, path, flags, mode)
}

func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Context) (fd int, err error) {
// FIXME: take into account context.Owner
return Openat(dirfd, path, flags, mode)
}

func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
return emulateRenameat(olddirfd, oldpath, newdirfd, newpath)
}
Expand Down
23 changes: 23 additions & 0 deletions internal/syscallcompat/sys_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package syscallcompat

import (
"fmt"
"runtime"
"sync"
"syscall"

Expand Down Expand Up @@ -75,6 +76,28 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
return syscall.Openat(dirfd, path, flags, mode)
}

// OpenatUser runs the Openat syscall in the context of a different user.
func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Context) (fd int, err error) {
if context != nil {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

err = syscall.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return -1, err
}
defer syscall.Setregid(-1, 0)

err = syscall.Setreuid(-1, int(context.Owner.Uid))
if err != nil {
return -1, err
}
defer syscall.Setreuid(-1, 0)
}

return Openat(dirfd, path, flags, mode)
}

// Renameat wraps the Renameat syscall.
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath)
Expand Down

0 comments on commit 03b9d65

Please sign in to comment.