diff options
| author | Jakob Unterwurzacher | 2021-06-02 19:10:36 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2021-06-02 19:10:36 +0200 | 
| commit | a38e5988bae3319a2c1c6745064f5785a0971d05 (patch) | |
| tree | 6ae7645bba6d4f1b265b6dc859db6c7bbce7165f | |
| parent | b23e21f61fc51ffa9c1c823778553925e1cc115e (diff) | |
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)
| -rw-r--r-- | internal/fusefrontend/node_xattr.go | 11 | ||||
| -rw-r--r-- | internal/fusefrontend/node_xattr_darwin.go | 3 | ||||
| -rw-r--r-- | internal/fusefrontend/node_xattr_linux.go | 6 | ||||
| -rw-r--r-- | internal/syscallcompat/sys_linux.go | 20 | 
4 files changed, 35 insertions, 5 deletions
| diff --git a/internal/fusefrontend/node_xattr.go b/internal/fusefrontend/node_xattr.go index 925dcbf..ceb10f1 100644 --- a/internal/fusefrontend/node_xattr.go +++ b/internal/fusefrontend/node_xattr.go @@ -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. diff --git a/internal/fusefrontend/node_xattr_darwin.go b/internal/fusefrontend/node_xattr_darwin.go index 82c0dff..0f61a5d 100644 --- a/internal/fusefrontend/node_xattr_darwin.go +++ b/internal/fusefrontend/node_xattr_darwin.go @@ -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 diff --git a/internal/fusefrontend/node_xattr_linux.go b/internal/fusefrontend/node_xattr_linux.go index 342bdf6..9698282 100644 --- a/internal/fusefrontend/node_xattr_linux.go +++ b/internal/fusefrontend/node_xattr_linux.go @@ -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) { diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go index 36ce7d5..45c18d2 100644 --- a/internal/syscallcompat/sys_linux.go +++ b/internal/syscallcompat/sys_linux.go @@ -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)) | 
