fusefrontend: run acl Setxattr in user context
The result of setting an acl depends on who runs the operation! Fixes fuse-xfstests generic/375 (see https://github.com/rfjakob/fuse-xfstests/wiki/results_2021-05-19)
This commit is contained in:
parent
b23e21f61f
commit
a38e5988ba
@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/hanwen/go-fuse/v2/fuse"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
)
|
||||
|
||||
@ -90,7 +92,12 @@ func (n *Node) Setxattr(ctx context.Context, attr string, data []byte, flags uin
|
||||
|
||||
// ACLs are passed through without encryption
|
||||
if isAcl(attr) {
|
||||
return n.setXAttr(attr, data, flags)
|
||||
// result of setting an acl depends on the user doing it
|
||||
var context *fuse.Context
|
||||
if rn.args.PreserveOwner {
|
||||
context = toFuseCtx(ctx)
|
||||
}
|
||||
return n.setXAttr(context, attr, data, flags)
|
||||
}
|
||||
|
||||
cAttr, err := rn.encryptXattrName(attr)
|
||||
@ -98,7 +105,7 @@ func (n *Node) Setxattr(ctx context.Context, attr string, data []byte, flags uin
|
||||
return syscall.EINVAL
|
||||
}
|
||||
cData := rn.encryptXattrValue(data)
|
||||
return n.setXAttr(cAttr, cData, flags)
|
||||
return n.setXAttr(nil, cAttr, cData, flags)
|
||||
}
|
||||
|
||||
// RemoveXAttr - FUSE call.
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/hanwen/go-fuse/v2/fs"
|
||||
"github.com/hanwen/go-fuse/v2/fuse"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
||||
)
|
||||
@ -40,7 +41,7 @@ func (n *Node) getXAttr(cAttr string) (out []byte, errno syscall.Errno) {
|
||||
return cData, 0
|
||||
}
|
||||
|
||||
func (n *Node) setXAttr(cAttr string, cData []byte, flags uint32) (errno syscall.Errno) {
|
||||
func (n *Node) setXAttr(context *fuse.Context, cAttr string, cData []byte, flags uint32) (errno syscall.Errno) {
|
||||
dirfd, cName, errno := n.prepareAtSyscall("")
|
||||
if errno != 0 {
|
||||
return
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/hanwen/go-fuse/v2/fs"
|
||||
"github.com/hanwen/go-fuse/v2/fuse"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
||||
)
|
||||
@ -30,7 +31,7 @@ func (n *Node) getXAttr(cAttr string) (out []byte, errno syscall.Errno) {
|
||||
return cData, 0
|
||||
}
|
||||
|
||||
func (n *Node) setXAttr(cAttr string, cData []byte, flags uint32) (errno syscall.Errno) {
|
||||
func (n *Node) setXAttr(context *fuse.Context, cAttr string, cData []byte, flags uint32) (errno syscall.Errno) {
|
||||
dirfd, cName, errno := n.prepareAtSyscall("")
|
||||
if errno != 0 {
|
||||
return
|
||||
@ -38,7 +39,8 @@ func (n *Node) setXAttr(cAttr string, cData []byte, flags uint32) (errno syscall
|
||||
defer syscall.Close(dirfd)
|
||||
|
||||
procPath := fmt.Sprintf("/proc/self/fd/%d/%s", dirfd, cName)
|
||||
return fs.ToErrno(unix.Lsetxattr(procPath, cAttr, cData, int(flags)))
|
||||
|
||||
return fs.ToErrno(syscallcompat.LsetxattrUser(procPath, cAttr, cData, int(flags), context))
|
||||
}
|
||||
|
||||
func (n *Node) removeXAttr(cAttr string) (errno syscall.Errno) {
|
||||
|
@ -130,6 +130,9 @@ func asUser(f func() (int, error), context *fuse.Context) (int, error) {
|
||||
//
|
||||
// It switches the current thread to the new user, performs the syscall,
|
||||
// and switches back.
|
||||
//
|
||||
// If `context` is nil, this function behaves like ordinary Openat (no
|
||||
// user switching).
|
||||
func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Context) (fd int, err error) {
|
||||
f := func() (int, error) {
|
||||
return Openat(dirfd, path, flags, mode)
|
||||
@ -143,6 +146,7 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
|
||||
}
|
||||
|
||||
// MknodatUser runs the Mknodat syscall in the context of a different user.
|
||||
// If `context` is nil, this function behaves like ordinary Mknodat.
|
||||
//
|
||||
// See OpenatUser() for how this works.
|
||||
func MknodatUser(dirfd int, path string, mode uint32, dev int, context *fuse.Context) (err error) {
|
||||
@ -195,6 +199,7 @@ func FchmodatNofollow(dirfd int, path string, mode uint32) (err error) {
|
||||
}
|
||||
|
||||
// SymlinkatUser runs the Symlinkat syscall in the context of a different user.
|
||||
// If `context` is nil, this function behaves like ordinary Symlinkat.
|
||||
//
|
||||
// See OpenatUser() for how this works.
|
||||
func SymlinkatUser(oldpath string, newdirfd int, newpath string, context *fuse.Context) (err error) {
|
||||
@ -207,6 +212,7 @@ func SymlinkatUser(oldpath string, newdirfd int, newpath string, context *fuse.C
|
||||
}
|
||||
|
||||
// MkdiratUser runs the Mkdirat syscall in the context of a different user.
|
||||
// If `context` is nil, this function behaves like ordinary Mkdirat.
|
||||
//
|
||||
// See OpenatUser() for how this works.
|
||||
func MkdiratUser(dirfd int, path string, mode uint32, context *fuse.Context) (err error) {
|
||||
@ -218,6 +224,20 @@ func MkdiratUser(dirfd int, path string, mode uint32, context *fuse.Context) (er
|
||||
return err
|
||||
}
|
||||
|
||||
// LsetxattrUser runs the Lsetxattr syscall in the context of a different user.
|
||||
// This is useful when setting ACLs, as the result depends on the user running
|
||||
// the operation (see fuse-xfstests generic/375).
|
||||
//
|
||||
// If `context` is nil, this function behaves like ordinary Lsetxattr.
|
||||
func LsetxattrUser(path string, attr string, data []byte, flags int, context *fuse.Context) (err error) {
|
||||
f := func() (int, error) {
|
||||
err := unix.Lsetxattr(path, attr, data, flags)
|
||||
return -1, err
|
||||
}
|
||||
_, err = asUser(f, context)
|
||||
return err
|
||||
}
|
||||
|
||||
func timesToTimespec(a *time.Time, m *time.Time) []unix.Timespec {
|
||||
ts := make([]unix.Timespec, 2)
|
||||
ts[0] = unix.Timespec(fuse.UtimeToTimespec(a))
|
||||
|
Loading…
Reference in New Issue
Block a user