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)
|
return nil, fuse.ToStatus(err)
|
||||||
}
|
}
|
||||||
defer syscall.Close(dirfd)
|
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
|
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
|
// Handle long file name
|
||||||
if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) {
|
if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) {
|
||||||
// Create ".name"
|
// Create ".name"
|
||||||
@ -255,14 +251,14 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
|
|||||||
return nil, fuse.ToStatus(err)
|
return nil, fuse.ToStatus(err)
|
||||||
}
|
}
|
||||||
// Create content
|
// 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 {
|
if err != nil {
|
||||||
nametransform.DeleteLongNameAt(dirfd, cName)
|
nametransform.DeleteLongNameAt(dirfd, cName)
|
||||||
return nil, fuse.ToStatus(err)
|
return nil, fuse.ToStatus(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create content, normal (short) file name
|
// 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 {
|
if err != nil {
|
||||||
// xfstests generic/488 triggers this
|
// xfstests generic/488 triggers this
|
||||||
if err == syscall.EMFILE {
|
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)
|
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)
|
f := os.NewFile(uintptr(fd), cName)
|
||||||
return NewFile(f, fs)
|
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)
|
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) {
|
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
|
||||||
return emulateRenameat(olddirfd, oldpath, newdirfd, newpath)
|
return emulateRenameat(olddirfd, oldpath, newdirfd, newpath)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package syscallcompat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"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)
|
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.
|
// Renameat wraps the Renameat syscall.
|
||||||
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
|
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
|
||||||
return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath)
|
return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath)
|
||||||
|
Loading…
Reference in New Issue
Block a user