diff options
author | Jakob Unterwurzacher | 2025-02-26 21:12:56 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2025-02-26 21:27:29 +0100 |
commit | 22cd9cf174e8a93787b01f6dd7b09247f9642286 (patch) | |
tree | a0503f917b4354eef61452d9a9c6976fdaca5393 /internal/syscallcompat/asuser_darwin.go | |
parent | 49d797effbc0888975c51ac45371d91fc59ea2dc (diff) |
syscallcompat: add asUser for darwin and make OpenatUser and friends shared
Diffstat (limited to 'internal/syscallcompat/asuser_darwin.go')
-rw-r--r-- | internal/syscallcompat/asuser_darwin.go | 46 |
1 files changed, 46 insertions, 0 deletions
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 +} |