aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/syscallcompat/asuser.go59
-rw-r--r--internal/syscallcompat/asuser_darwin.go46
-rw-r--r--internal/syscallcompat/sys_darwin.go75
-rw-r--r--internal/syscallcompat/sys_linux.go53
4 files changed, 105 insertions, 128 deletions
diff --git a/internal/syscallcompat/asuser.go b/internal/syscallcompat/asuser.go
new file mode 100644
index 0000000..0c083ec
--- /dev/null
+++ b/internal/syscallcompat/asuser.go
@@ -0,0 +1,59 @@
+package syscallcompat
+
+import (
+ "golang.org/x/sys/unix"
+
+ "github.com/hanwen/go-fuse/v2/fuse"
+)
+
+// OpenatUser runs the Openat syscall in the context of a different user.
+// 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)
+ }
+ return asUser(f, context)
+}
+
+// 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) {
+ f := func() (int, error) {
+ err := Mknodat(dirfd, path, mode, dev)
+ return -1, err
+ }
+ _, err = asUser(f, context)
+ return err
+}
+
+// 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) {
+ f := func() (int, error) {
+ err := unix.Symlinkat(oldpath, newdirfd, newpath)
+ return -1, err
+ }
+ _, err = asUser(f, context)
+ return err
+}
+
+// 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) {
+ f := func() (int, error) {
+ err := unix.Mkdirat(dirfd, path, mode)
+ return -1, err
+ }
+ _, err = asUser(f, context)
+ return err
+}
diff --git a/internal/syscallcompat/asuser_darwin.go b/internal/syscallcompat/asuser_darwin.go
new file mode 100644
index 0000000..5da2782
--- /dev/null
+++ b/internal/syscallcompat/asuser_darwin.go
@@ -0,0 +1,46 @@
+package syscallcompat
+
+import (
+ "runtime"
+ "syscall"
+
+ "github.com/hanwen/go-fuse/v2/fuse"
+)
+
+// asUser runs `f()` under the effective uid, gid, groups specified
+// in `context`.
+//
+// If `context` is nil, `f()` is executed directly without switching user id.
+func asUser(f func() (int, error), context *fuse.Context) (int, error) {
+ if context == nil {
+ return f()
+ }
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ err := pthread_setugid_np(context.Owner.Uid, context.Owner.Gid)
+ if err != nil {
+ return -1, err
+ }
+
+ const (
+ // KAUTH_UID_NONE and KAUTH_GID_NONE are special values to
+ // revert permissions to the process credentials.
+ KAUTH_UID_NONE = ^uint32(0) - 100
+ KAUTH_GID_NONE = ^uint32(0) - 100
+ )
+
+ defer pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE)
+
+ return f()
+}
+
+// Unfortunately pthread_setugid_np does not have a syscall wrapper yet.
+func pthread_setugid_np(uid uint32, gid uint32) (err error) {
+ _, _, e1 := syscall.RawSyscall(syscall.SYS_SETTID, uintptr(uid), uintptr(gid), 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
diff --git a/internal/syscallcompat/sys_darwin.go b/internal/syscallcompat/sys_darwin.go
index 06f09f0..cf2f3f0 100644
--- a/internal/syscallcompat/sys_darwin.go
+++ b/internal/syscallcompat/sys_darwin.go
@@ -3,7 +3,6 @@ package syscallcompat
import (
"log"
"path/filepath"
- "runtime"
"syscall"
"time"
"unsafe"
@@ -26,22 +25,8 @@ const (
RENAME_NOREPLACE = 1
RENAME_EXCHANGE = 2
RENAME_WHITEOUT = 4
-
- // KAUTH_UID_NONE and KAUTH_GID_NONE are special values to
- // revert permissions to the process credentials.
- KAUTH_UID_NONE = ^uint32(0) - 100
- KAUTH_GID_NONE = ^uint32(0) - 100
)
-// Unfortunately pthread_setugid_np does not have a syscall wrapper yet.
-func pthread_setugid_np(uid uint32, gid uint32) (err error) {
- _, _, e1 := syscall.RawSyscall(syscall.SYS_SETTID, uintptr(uid), uintptr(gid), 0)
- if e1 != 0 {
- err = e1
- }
- return
-}
-
// Unfortunately fsetattrlist does not have a syscall wrapper yet.
func fsetattrlist(fd int, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
_, _, e1 := syscall.Syscall6(syscall.SYS_FSETATTRLIST, uintptr(fd), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
@@ -84,74 +69,14 @@ func Dup3(oldfd int, newfd int, flags int) (err error) {
//// Emulated Syscalls (see emulate.go) ////////////////
////////////////////////////////////////////////////////
-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 = pthread_setugid_np(context.Owner.Uid, context.Owner.Gid)
- if err != nil {
- return -1, err
- }
- defer pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE)
- }
-
- return Openat(dirfd, path, flags, mode)
-}
-
func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
return emulateMknodat(dirfd, path, mode, dev)
}
-func MknodatUser(dirfd int, path string, mode uint32, dev int, context *fuse.Context) (err error) {
- if context != nil {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- err = pthread_setugid_np(context.Owner.Uid, context.Owner.Gid)
- if err != nil {
- return err
- }
- defer pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE)
- }
-
- return Mknodat(dirfd, path, mode, dev)
-}
-
func FchmodatNofollow(dirfd int, path string, mode uint32) (err error) {
return unix.Fchmodat(dirfd, path, mode, unix.AT_SYMLINK_NOFOLLOW)
}
-func SymlinkatUser(oldpath string, newdirfd int, newpath string, context *fuse.Context) (err error) {
- if context != nil {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- err = pthread_setugid_np(context.Owner.Uid, context.Owner.Gid)
- if err != nil {
- return err
- }
- defer pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE)
- }
-
- return unix.Symlinkat(oldpath, newdirfd, newpath)
-}
-
-func MkdiratUser(dirfd int, path string, mode uint32, context *fuse.Context) (err error) {
- if context != nil {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- err = pthread_setugid_np(context.Owner.Uid, context.Owner.Gid)
- if err != nil {
- return err
- }
- defer pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE)
- }
-
- return unix.Mkdirat(dirfd, path, mode)
-}
-
type attrList struct {
bitmapCount uint16
_ uint16
diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go
index d769f96..6414a64 100644
--- a/internal/syscallcompat/sys_linux.go
+++ b/internal/syscallcompat/sys_linux.go
@@ -92,38 +92,11 @@ func getSupplementaryGroups(pid uint32) (gids []int) {
return nil
}
-// OpenatUser runs the Openat syscall in the context of a different user.
-//
-// 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)
- }
- return asUser(f, context)
-}
-
// Mknodat wraps the Mknodat syscall.
func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
return syscall.Mknodat(dirfd, path, mode, dev)
}
-// 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) {
- f := func() (int, error) {
- err := Mknodat(dirfd, path, mode, dev)
- return -1, err
- }
- _, err = asUser(f, context)
- return err
-}
-
// Dup3 wraps the Dup3 syscall. We want to use Dup3 rather than Dup2 because Dup2
// is not implemented on arm64.
func Dup3(oldfd int, newfd int, flags int) (err error) {
@@ -164,32 +137,6 @@ func FchmodatNofollow(dirfd int, path string, mode uint32) (err error) {
return syscall.Chmod(procPath, mode)
}
-// 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) {
- f := func() (int, error) {
- err := unix.Symlinkat(oldpath, newdirfd, newpath)
- return -1, err
- }
- _, err = asUser(f, context)
- return err
-}
-
-// 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) {
- f := func() (int, error) {
- err := unix.Mkdirat(dirfd, path, mode)
- return -1, err
- }
- _, err = asUser(f, context)
- 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).