From 853cd1f4a61396cccb91522ed59af52d61aa8371 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Fri, 27 May 2016 15:02:31 -0700 Subject: syscall: call setgroups for no groups on GNU/Linux Skip setgroups only for one particular case: GidMappings != nil and GidMappingsEnableSetgroup == false and list of supplementary groups is empty. This patch returns pre-1.5 behavior for simple exec and still allows to use GidMappings with non-empty Credential. Change-Id: Ia91c77e76ec5efab7a7f78134ffb529910108fc1 Reviewed-on: https://go-review.googlesource.com/23524 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/syscall/exec_linux_test.go | 61 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'src/syscall/exec_linux_test.go') diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 395dd99039..1afe88cb1b 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -26,7 +26,7 @@ func isChrooted(t *testing.T) bool { return root.Sys().(*syscall.Stat_t).Ino != 2 } -func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd { +func checkUserNS(t *testing.T) { if _, err := os.Stat("/proc/self/ns/user"); err != nil { if os.IsNotExist(err) { t.Skip("kernel doesn't support user namespaces") @@ -56,6 +56,10 @@ func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd { if os.Getenv("GO_BUILDER_NAME") != "" && os.Getenv("IN_KUBERNETES") == "1" { t.Skip("skipping test on Kubernetes-based builders; see Issue 12815") } +} + +func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd { + checkUserNS(t) cmd := exec.Command("whoami") cmd.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWUSER, @@ -161,3 +165,58 @@ func TestUnshare(t *testing.T) { t.Fatalf("Expected 3 lines of output, got %d", len(lines)) } } + +func TestGroupCleanup(t *testing.T) { + if os.Getuid() != 0 { + t.Skip("we need root for credential") + } + cmd := exec.Command("id") + cmd.SysProcAttr = &syscall.SysProcAttr{ + Credential: &syscall.Credential{ + Uid: 0, + Gid: 0, + }, + } + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("Cmd failed with err %v, output: %s", err, out) + } + strOut := strings.TrimSpace(string(out)) + expected := "uid=0(root) gid=0(root) groups=0(root)" + if strOut != expected { + t.Fatalf("id command output: %s, expected: %s", strOut, expected) + } +} + +func TestGroupCleanupUserNamespace(t *testing.T) { + if os.Getuid() != 0 { + t.Skip("we need root for credential") + } + checkUserNS(t) + cmd := exec.Command("id") + uid, gid := os.Getuid(), os.Getgid() + cmd.SysProcAttr = &syscall.SysProcAttr{ + Cloneflags: syscall.CLONE_NEWUSER, + Credential: &syscall.Credential{ + Uid: uint32(uid), + Gid: uint32(gid), + }, + UidMappings: []syscall.SysProcIDMap{ + {ContainerID: 0, HostID: uid, Size: 1}, + }, + GidMappings: []syscall.SysProcIDMap{ + {ContainerID: 0, HostID: gid, Size: 1}, + }, + } + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("Cmd failed with err %v, output: %s", err, out) + } + strOut := strings.TrimSpace(string(out)) + // there are two possible outs + expected1 := "uid=0(root) gid=0(root) groups=0(root)" + expected2 := "uid=0(root) gid=0(root) groups=0(root),65534(nobody)" + if strOut != expected1 && strOut != expected2 { + t.Fatalf("id command output: %s, expected: %s or %s", strOut, expected1, expected2) + } +} -- cgit v1.3