fusefrontend: -allow_other: Use OpenatUser in Create FUSE call.
Revert commit b22cc03c75
.
Instead of manually adjusting the user and mode after creating the
file, adjust effective permissions and let the kernel deal with it.
Related to https://github.com/rfjakob/gocryptfs/issues/338.
This commit is contained in:
parent
669322482a
commit
03b9d65cce
@ -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"
|
||||
@ -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 {
|
||||
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package syscallcompat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user