aboutsummaryrefslogtreecommitdiff
path: root/src/syscall/exec_linux_test.go
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2019-01-07 10:18:42 -0800
committerIan Lance Taylor <iant@golang.org>2019-03-08 20:53:16 +0000
commit5930c7de933c4d826926396f715bae63333143a2 (patch)
tree160dffcb059f1641072790eff0c2097fa4702854 /src/syscall/exec_linux_test.go
parentf1d5ce0185fe184c016016d55f1718778b799f6d (diff)
downloadgo-5930c7de933c4d826926396f715bae63333143a2.tar.gz
go-5930c7de933c4d826926396f715bae63333143a2.zip
syscall: add all ambient capabilities into permitted and inheritable sets
According to the prctl man page, each capability from the ambient set must already be present in both the permitted and the inheritable sets of the process. exec_linux_test suggests configuring the capabilities in the parent process. This doesn't look nice, because: * Capabilities are a per-thread attribute, so we need to use LockOSThread. * Need to restore capabilities after creating a process. * Doesn't work with user namespaces, because a process gets capabilities when a namespace is created. Fixes #23152 Change-Id: Iba23e530fc7b9f5182d602fe855f82218f354219 Reviewed-on: https://go-review.googlesource.com/c/go/+/156577 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/syscall/exec_linux_test.go')
-rw-r--r--src/syscall/exec_linux_test.go56
1 files changed, 39 insertions, 17 deletions
diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go
index ac5745bc80..dc16a9d9fe 100644
--- a/src/syscall/exec_linux_test.go
+++ b/src/syscall/exec_linux_test.go
@@ -436,7 +436,7 @@ func TestUnshareMountNameSpaceChroot(t *testing.T) {
type capHeader struct {
version uint32
- pid int
+ pid int32
}
type capData struct {
@@ -446,6 +446,7 @@ type capData struct {
}
const CAP_SYS_TIME = 25
+const CAP_SYSLOG = 34
type caps struct {
hdr capHeader
@@ -506,15 +507,28 @@ func TestAmbientCapsHelper(*testing.T) {
fmt.Fprintln(os.Stderr, "CAP_SYS_TIME unexpectedly not in the effective capability mask")
os.Exit(2)
}
+ if caps.data[1].effective&(1<<uint(CAP_SYSLOG&31)) == 0 {
+ fmt.Fprintln(os.Stderr, "CAP_SYSLOG unexpectedly not in the effective capability mask")
+ os.Exit(2)
+ }
}
func TestAmbientCaps(t *testing.T) {
- skipInContainer(t)
// Make sure we are running as root so we have permissions to use unshare
// and create a network namespace.
if os.Getuid() != 0 {
t.Skip("kernel prohibits unshare in unprivileged process, unless using user namespace")
}
+
+ testAmbientCaps(t, false)
+}
+
+func TestAmbientCapsUserns(t *testing.T) {
+ testAmbientCaps(t, true)
+}
+
+func testAmbientCaps(t *testing.T, userns bool) {
+ skipInContainer(t)
mustSupportAmbientCaps(t)
// When running under the Go continuous build, skip tests for
@@ -530,20 +544,6 @@ func TestAmbientCaps(t *testing.T) {
t.Skip("skipping test on android; see Issue 27327")
}
- caps, err := getCaps()
- if err != nil {
- t.Fatal(err)
- }
-
- // Add CAP_SYS_TIME to the permitted and inheritable capability mask,
- // otherwise we will not be able to add it to the ambient capability mask.
- caps.data[0].permitted |= 1 << uint(CAP_SYS_TIME)
- caps.data[0].inheritable |= 1 << uint(CAP_SYS_TIME)
-
- if _, _, errno := syscall.Syscall(syscall.SYS_CAPSET, uintptr(unsafe.Pointer(&caps.hdr)), uintptr(unsafe.Pointer(&caps.data[0])), 0); errno != 0 {
- t.Fatalf("SYS_CAPSET: %v", errno)
- }
-
u, err := user.Lookup("nobody")
if err != nil {
t.Fatal(err)
@@ -588,7 +588,29 @@ func TestAmbientCaps(t *testing.T) {
Uid: uint32(uid),
Gid: uint32(gid),
},
- AmbientCaps: []uintptr{CAP_SYS_TIME},
+ AmbientCaps: []uintptr{CAP_SYS_TIME, CAP_SYSLOG},
+ }
+ if userns {
+ cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWUSER
+ const nobody = 65534
+ uid := os.Getuid()
+ gid := os.Getgid()
+ cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{
+ ContainerID: int(nobody),
+ HostID: int(uid),
+ Size: int(1),
+ }}
+ cmd.SysProcAttr.GidMappings = []syscall.SysProcIDMap{{
+ ContainerID: int(nobody),
+ HostID: int(gid),
+ Size: int(1),
+ }}
+
+ // Set credentials to run as user and group nobody.
+ cmd.SysProcAttr.Credential = &syscall.Credential{
+ Uid: nobody,
+ Gid: nobody,
+ }
}
if err := cmd.Run(); err != nil {
t.Fatal(err.Error())