aboutsummaryrefslogtreecommitdiff
path: root/internal/syscallcompat/sys_linux.go
diff options
context:
space:
mode:
authorSebastian Lackner2019-05-01 13:18:44 +0200
committerJakob Unterwurzacher2019-05-01 17:52:07 +0200
commita97d14c42d902e53efdb42e9b32c4a39559fc262 (patch)
tree6849755b938c89c2c458f10b3ee428dbf6dbebfd /internal/syscallcompat/sys_linux.go
parent96935e16b9167dc3c472505872b3fc5235203a05 (diff)
syscallcompat: fetch supplementary groups for OpenatUser & friends
Handled the same way in GlusterFS, disorderfs, libfuse. Fixes https://github.com/rfjakob/gocryptfs/issues/394
Diffstat (limited to 'internal/syscallcompat/sys_linux.go')
-rw-r--r--internal/syscallcompat/sys_linux.go53
1 files changed, 53 insertions, 0 deletions
diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go
index 92d8183..ac7891a 100644
--- a/internal/syscallcompat/sys_linux.go
+++ b/internal/syscallcompat/sys_linux.go
@@ -3,7 +3,10 @@ package syscallcompat
import (
"fmt"
+ "io/ioutil"
"runtime"
+ "strconv"
+ "strings"
"sync"
"syscall"
"time"
@@ -59,12 +62,44 @@ func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
return syscall.Fallocate(fd, mode, off, len)
}
+func getSupplementaryGroups(pid uint32) (gids []int) {
+ procPath := fmt.Sprintf("/proc/%d/task/%d/status", pid, pid)
+ blob, err := ioutil.ReadFile(procPath)
+ if err != nil {
+ return nil
+ }
+
+ lines := strings.Split(string(blob), "\n")
+ for _, line := range lines {
+ if strings.HasPrefix(line, "Groups:") {
+ f := strings.Fields(line[7:])
+ gids = make([]int, len(f))
+ for i := range gids {
+ val, err := strconv.ParseInt(f[i], 10, 32)
+ if err != nil {
+ return nil
+ }
+ gids[i] = int(val)
+ }
+ return gids
+ }
+ }
+
+ return nil
+}
+
// OpenatUser runs the Openat syscall in the context of a different user.
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))
+ if err != nil {
+ return -1, err
+ }
+ defer syscall.Setgroups(nil)
+
err = syscall.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return -1, err
@@ -92,6 +127,12 @@ func MknodatUser(dirfd int, path string, mode uint32, dev int, context *fuse.Con
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ err = syscall.Setgroups(getSupplementaryGroups(context.Pid))
+ if err != nil {
+ return err
+ }
+ defer syscall.Setgroups(nil)
+
err = syscall.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return err
@@ -154,6 +195,12 @@ func SymlinkatUser(oldpath string, newdirfd int, newpath string, context *fuse.C
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ err = syscall.Setgroups(getSupplementaryGroups(context.Pid))
+ if err != nil {
+ return err
+ }
+ defer syscall.Setgroups(nil)
+
err = syscall.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return err
@@ -176,6 +223,12 @@ func MkdiratUser(dirfd int, path string, mode uint32, context *fuse.Context) (er
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ err = syscall.Setgroups(getSupplementaryGroups(context.Pid))
+ if err != nil {
+ return err
+ }
+ defer syscall.Setgroups(nil)
+
err = syscall.Setregid(-1, int(context.Owner.Gid))
if err != nil {
return err