diff options
author | Jakob Unterwurzacher | 2025-02-06 21:54:33 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2025-02-06 21:59:45 +0100 |
commit | cd47ab015e5d4a7ecaee747796fb89b7597b4fc1 (patch) | |
tree | 1e4440f38ffd4181cfc2caa8ca908d064e3fcb32 | |
parent | 3ad8759d55419df51e3435bd40ea9cc62e3d4c87 (diff) |
Private copies of per-thread Setreuid/Setegid/Setgroups.
https://github.com/rfjakob/gocryptfs/issues/893
https://github.com/rfjakob/gocryptfs/issues/892
-rw-r--r-- | internal/syscallcompat/thread_credentials.go | 32 | ||||
-rw-r--r-- | internal/syscallcompat/thread_credentials_368_arm.go | 35 | ||||
-rw-r--r-- | internal/syscallcompat/thread_credentials_other.go | 35 |
3 files changed, 102 insertions, 0 deletions
diff --git a/internal/syscallcompat/thread_credentials.go b/internal/syscallcompat/thread_credentials.go new file mode 100644 index 0000000..3ef5233 --- /dev/null +++ b/internal/syscallcompat/thread_credentials.go @@ -0,0 +1,32 @@ +//go:build linux + +// golang.org/x/sys/unix commit +// https://github.com/golang/sys/commit/d0df966e6959f00dc1c74363e537872647352d51 +// changed unix.Setreuid/unix.Setregid functions to affect the whole thread, which is +// what gocryptfs does NOT want (https://github.com/rfjakob/gocryptfs/issues/893). +// The functions Setreuid/Setegid are copy-pasted from one commit before +// (9e1f76180b77a12eb07c82eb8e1ea8a7f8d202e7). +// +// Looking at the diff at https://github.com/golang/sys/commit/d0df966e6959f00dc1c74363e537872647352d51 +// we see that only two architectures, 386 and arm, use SYS_SETREUID32/SYS_SETREGID32 +// (see "man 2 setreuid" for why). +// All the others architectures use SYS_SETREUID/SYS_SETREGID. +// +// As of golang.org/x/sys/unix v0.30.0, Setgroups/setgroups is still per-thread, but +// it is likely that this will change, too. Setgroups/setgroups are copy-pasted from +// v0.30.0. The SYS_SETGROUPS32/SYS_SETGROUPS split is the same as for Setreuid. +// +// Note: _Gid_t is always uint32 on linux, so we can directly use uint32 for setgroups. +package syscallcompat + +func Setgroups(gids []int) (err error) { + if len(gids) == 0 { + return setgroups(0, nil) + } + + a := make([]uint32, len(gids)) + for i, v := range gids { + a[i] = uint32(v) + } + return setgroups(len(a), &a[0]) +} diff --git a/internal/syscallcompat/thread_credentials_368_arm.go b/internal/syscallcompat/thread_credentials_368_arm.go new file mode 100644 index 0000000..1244160 --- /dev/null +++ b/internal/syscallcompat/thread_credentials_368_arm.go @@ -0,0 +1,35 @@ +//go:build (linux && 386) || (linux && arm) + +package syscallcompat + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +// See thread_credentials.go for docs + +func Setreuid(ruid int, euid int) (err error) { + _, _, e1 := unix.RawSyscall(unix.SYS_SETREUID32, uintptr(ruid), uintptr(euid), 0) + if e1 != 0 { + err = e1 + } + return +} + +func Setregid(rgid int, egid int) (err error) { + _, _, e1 := unix.RawSyscall(unix.SYS_SETREGID32, uintptr(rgid), uintptr(egid), 0) + if e1 != 0 { + err = e1 + } + return +} + +func setgroups(n int, list *uint32) (err error) { + _, _, e1 := unix.RawSyscall(unix.SYS_SETGROUPS32, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + if e1 != 0 { + err = e1 + } + return +} diff --git a/internal/syscallcompat/thread_credentials_other.go b/internal/syscallcompat/thread_credentials_other.go new file mode 100644 index 0000000..e3c78d0 --- /dev/null +++ b/internal/syscallcompat/thread_credentials_other.go @@ -0,0 +1,35 @@ +//go:build !((linux && 386) || (linux && arm)) + +package syscallcompat + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +// See thread_credentials.go for docs + +func Setreuid(ruid int, euid int) (err error) { + _, _, e1 := unix.RawSyscall(unix.SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) + if e1 != 0 { + err = e1 + } + return +} + +func Setregid(rgid int, egid int) (err error) { + _, _, e1 := unix.RawSyscall(unix.SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) + if e1 != 0 { + err = e1 + } + return +} + +func setgroups(n int, list *uint32) (err error) { + _, _, e1 := unix.RawSyscall(unix.SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + if e1 != 0 { + err = e1 + } + return +} |