summaryrefslogtreecommitdiff
path: root/internal/syscallcompat/sys_linux.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2021-02-06 11:13:22 +0100
committerJakob Unterwurzacher2021-02-06 11:38:25 +0100
commit80a651a19474c78b1b2716cbf8c85ffd78698823 (patch)
treea5c83754a197c789c26e5a15bf24707a1cd9113e /internal/syscallcompat/sys_linux.go
parent3ab1bcf1c5aacafe4339564ff0a09c349d3201a0 (diff)
syscallcompat: MknodatUser: work around changed syscall.Setgroups semantics
Since go1.16beta1 (commit d1b1145cace8b968307f9311ff611e4bb810710c , https://go-review.googlesource.com/c/go/+/210639 ) syscall.{Setgroups,Setregid,Setreuid} affects all threads, which is exactly what we not want. We now use unix.{Setgroups,Setregid,Setreuid} instead. Workarounds https://github.com/golang/go/issues/1435 .
Diffstat (limited to 'internal/syscallcompat/sys_linux.go')
-rw-r--r--internal/syscallcompat/sys_linux.go64
1 files changed, 40 insertions, 24 deletions
diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go
index 06b9696..d178323 100644
--- a/internal/syscallcompat/sys_linux.go
+++ b/internal/syscallcompat/sys_linux.go
@@ -92,28 +92,38 @@ func getSupplementaryGroups(pid uint32) (gids []int) {
}
// 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.
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 = syscall.Setgroups(getSupplementaryGroups(context.Pid))
+ // Since go1.16beta1 (commit d1b1145cace8b968307f9311ff611e4bb810710c ,
+ // https://go-review.googlesource.com/c/go/+/210639 )
+ // syscall.{Setgroups,Setregid,Setreuid} affects all threads, which
+ // is exactly what we not want.
+ //
+ // We now use unix.{Setgroups,Setregid,Setreuid} instead.
+
+ err = unix.Setgroups(getSupplementaryGroups(context.Pid))
if err != nil {
return -1, err
}
- defer syscall.Setgroups(nil)
+ defer unix.Setgroups(nil)
- err = syscall.Setregid(-1, int(context.Owner.Gid))
+ err = unix.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return -1, err
}
- defer syscall.Setregid(-1, 0)
+ defer unix.Setregid(-1, 0)
- err = syscall.Setreuid(-1, int(context.Owner.Uid))
+ err = unix.Setreuid(-1, int(context.Owner.Uid))
if err != nil {
return -1, err
}
- defer syscall.Setreuid(-1, 0)
+ defer unix.Setreuid(-1, 0)
}
return Openat(dirfd, path, flags, mode)
@@ -125,28 +135,30 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
}
// MknodatUser runs the Mknodat syscall in the context of a different user.
+//
+// See OpenatUser() for how this works.
func MknodatUser(dirfd int, path string, mode uint32, dev int, context *fuse.Context) (err error) {
if context != nil {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- err = syscall.Setgroups(getSupplementaryGroups(context.Pid))
+ err = unix.Setgroups(getSupplementaryGroups(context.Pid))
if err != nil {
return err
}
- defer syscall.Setgroups(nil)
+ defer unix.Setgroups(nil)
- err = syscall.Setregid(-1, int(context.Owner.Gid))
+ err = unix.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return err
}
- defer syscall.Setregid(-1, 0)
+ defer unix.Setregid(-1, 0)
- err = syscall.Setreuid(-1, int(context.Owner.Uid))
+ err = unix.Setreuid(-1, int(context.Owner.Uid))
if err != nil {
return err
}
- defer syscall.Setreuid(-1, 0)
+ defer unix.Setreuid(-1, 0)
}
return Mknodat(dirfd, path, mode, dev)
@@ -193,56 +205,60 @@ func FchmodatNofollow(dirfd int, path string, mode uint32) (err error) {
}
// SymlinkatUser runs the Symlinkat syscall in the context of a different user.
+//
+// See OpenatUser() for how this works.
func SymlinkatUser(oldpath string, newdirfd int, newpath string, context *fuse.Context) (err error) {
if context != nil {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- err = syscall.Setgroups(getSupplementaryGroups(context.Pid))
+ err = unix.Setgroups(getSupplementaryGroups(context.Pid))
if err != nil {
return err
}
- defer syscall.Setgroups(nil)
+ defer unix.Setgroups(nil)
- err = syscall.Setregid(-1, int(context.Owner.Gid))
+ err = unix.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return err
}
- defer syscall.Setregid(-1, 0)
+ defer unix.Setregid(-1, 0)
- err = syscall.Setreuid(-1, int(context.Owner.Uid))
+ err = unix.Setreuid(-1, int(context.Owner.Uid))
if err != nil {
return err
}
- defer syscall.Setreuid(-1, 0)
+ defer unix.Setreuid(-1, 0)
}
return Symlinkat(oldpath, newdirfd, newpath)
}
// MkdiratUser runs the Mkdirat syscall in the context of a different user.
+//
+// See OpenatUser() for how this works.
func MkdiratUser(dirfd int, path string, mode uint32, caller *fuse.Caller) (err error) {
if caller != nil {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- err = syscall.Setgroups(getSupplementaryGroups(caller.Pid))
+ err = unix.Setgroups(getSupplementaryGroups(caller.Pid))
if err != nil {
return err
}
- defer syscall.Setgroups(nil)
+ defer unix.Setgroups(nil)
- err = syscall.Setregid(-1, int(caller.Gid))
+ err = unix.Setregid(-1, int(caller.Gid))
if err != nil {
return err
}
- defer syscall.Setregid(-1, 0)
+ defer unix.Setregid(-1, 0)
- err = syscall.Setreuid(-1, int(caller.Uid))
+ err = unix.Setreuid(-1, int(caller.Uid))
if err != nil {
return err
}
- defer syscall.Setreuid(-1, 0)
+ defer unix.Setreuid(-1, 0)
}
return Mkdirat(dirfd, path, mode)