go/src/syscall/exec_linux_test.go

675 lines
19 KiB
Go
Raw Normal View History

// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux
package syscall_test
import (
syscall: add CgroupFD support for ForkExec on Linux Implement CLONE_INTO_CGROUP feature, allowing to put a child in a specified cgroup in a clean and simple way. Note that the feature only works for cgroup v2, and requires Linux kernel 5.7 or newer. Using the feature requires a new syscall, clone3. Currently this is the only reason to use clone3, but the code is structured in a way so that other cases may be easily added in the future. Add a test case. While at it, try to simplify the syscall calling code in forkAndExecInChild1, which became complicated over time because: 1. It was using either rawVforkSyscall or RawSyscall6 depending on whether CLONE_NEWUSER was set. 2. On Linux/s390, the first two arguments to clone(2) system call are swapped (which deserved a mention in Linux ABI hall of shame). It was worked around in rawVforkSyscall on s390, but had to be implemented via a switch/case when using RawSyscall6, making the code less clear. Let's - modify rawVforkSyscall to have two arguments (which is also required for clone3); - remove the arguments workaround from s390 asm, instead implementing arguments swap in the caller (which still looks ugly but at least it's done once and is clearly documented now); - use rawVforkSyscall for all cases (since it is essentially similar to RawSyscall6, except for having less parameters, not returning r2, and saving/restoring the return address before/after syscall on 386 and amd64). Updates #51246. Change-Id: Ifcd418ebead9257177338ffbcccd0bdecb94474e Reviewed-on: https://go-review.googlesource.com/c/go/+/417695 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-14 21:18:15 -07:00
"bytes"
"errors"
"flag"
"fmt"
"internal/platform"
"internal/testenv"
"io"
"os"
"os/exec"
"os/user"
syscall: add CgroupFD support for ForkExec on Linux Implement CLONE_INTO_CGROUP feature, allowing to put a child in a specified cgroup in a clean and simple way. Note that the feature only works for cgroup v2, and requires Linux kernel 5.7 or newer. Using the feature requires a new syscall, clone3. Currently this is the only reason to use clone3, but the code is structured in a way so that other cases may be easily added in the future. Add a test case. While at it, try to simplify the syscall calling code in forkAndExecInChild1, which became complicated over time because: 1. It was using either rawVforkSyscall or RawSyscall6 depending on whether CLONE_NEWUSER was set. 2. On Linux/s390, the first two arguments to clone(2) system call are swapped (which deserved a mention in Linux ABI hall of shame). It was worked around in rawVforkSyscall on s390, but had to be implemented via a switch/case when using RawSyscall6, making the code less clear. Let's - modify rawVforkSyscall to have two arguments (which is also required for clone3); - remove the arguments workaround from s390 asm, instead implementing arguments swap in the caller (which still looks ugly but at least it's done once and is clearly documented now); - use rawVforkSyscall for all cases (since it is essentially similar to RawSyscall6, except for having less parameters, not returning r2, and saving/restoring the return address before/after syscall on 386 and amd64). Updates #51246. Change-Id: Ifcd418ebead9257177338ffbcccd0bdecb94474e Reviewed-on: https://go-review.googlesource.com/c/go/+/417695 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-14 21:18:15 -07:00
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"testing"
"unsafe"
)
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
// whoamiNEWUSER returns a command that runs "whoami" with CLONE_NEWUSER,
// mapping uid and gid 0 to the actual uid and gid of the test.
func whoamiNEWUSER(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd {
t.Helper()
testenv.MustHaveExecPath(t, "whoami")
cmd := testenv.Command(t, "whoami")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUSER,
UidMappings: []syscall.SysProcIDMap{
{ContainerID: 0, HostID: uid, Size: 1},
},
GidMappings: []syscall.SysProcIDMap{
{ContainerID: 0, HostID: gid, Size: 1},
},
GidMappingsEnableSetgroups: setgroups,
}
return cmd
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
func TestCloneNEWUSERAndRemap(t *testing.T) {
for _, setgroups := range []bool{false, true} {
setgroups := setgroups
t.Run(fmt.Sprintf("setgroups=%v", setgroups), func(t *testing.T) {
uid := os.Getuid()
gid := os.Getgid()
cmd := whoamiNEWUSER(t, uid, gid, setgroups)
out, err := cmd.CombinedOutput()
t.Logf("%v: %v", cmd, err)
if uid != 0 && setgroups {
t.Logf("as non-root, expected permission error due to unprivileged gid_map")
if !os.IsPermission(err) {
if err == nil {
t.Skipf("unexpected success: probably old kernel without security fix?")
}
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: CLONE_NEWUSER appears to be unsupported")
}
t.Fatalf("got non-permission error") // Already logged above.
}
return
}
if err != nil {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
// May be inside a container that disallows CLONE_NEWUSER.
t.Skipf("skipping: CLONE_NEWUSER appears to be unsupported")
}
t.Fatalf("unexpected command failure; output:\n%s", out)
}
sout := strings.TrimSpace(string(out))
want := "root"
if sout != want {
t.Fatalf("whoami = %q; want %q", out, want)
}
})
}
}
func TestEmptyCredGroupsDisableSetgroups(t *testing.T) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
cmd := whoamiNEWUSER(t, os.Getuid(), os.Getgid(), false)
cmd.SysProcAttr.Credential = &syscall.Credential{}
if err := cmd.Run(); err != nil {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: %v: %v", cmd, err)
}
t.Fatal(err)
}
}
func TestUnshare(t *testing.T) {
path := "/proc/net/dev"
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
t.Skip("kernel doesn't support proc filesystem")
}
if os.IsPermission(err) {
t.Skip("unable to test proc filesystem due to permissions")
}
t.Fatal(err)
}
b, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
orig := strings.TrimSpace(string(b))
if strings.Contains(orig, "lo:") && strings.Count(orig, ":") == 1 {
// This test expects there to be at least 1 more network interface
// in addition to the local network interface, so that it can tell
// that unshare worked.
t.Skip("not enough network interfaces to test unshare with")
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
cmd := testenv.Command(t, "cat", path)
cmd.SysProcAttr = &syscall.SysProcAttr{
Unshareflags: syscall.CLONE_NEWNET,
}
out, err := cmd.CombinedOutput()
if err != nil {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
// CLONE_NEWNET does not appear to be supported.
t.Skipf("skipping due to permission error: %v", err)
}
t.Fatalf("Cmd failed with err %v, output: %s", err, out)
}
// Check there is only the local network interface.
sout := strings.TrimSpace(string(out))
if !strings.Contains(sout, "lo:") {
t.Fatalf("Expected lo network interface to exist, got %s", sout)
}
origLines := strings.Split(orig, "\n")
lines := strings.Split(sout, "\n")
if len(lines) >= len(origLines) {
t.Logf("%s before unshare:\n%s", path, orig)
t.Logf("%s after unshare:\n%s", path, sout)
t.Fatalf("Got %d lines of output, want < %d", len(lines), len(origLines))
}
}
func TestGroupCleanup(t *testing.T) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
testenv.MustHaveExecPath(t, "id")
cmd := testenv.Command(t, "id")
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: 0,
Gid: 0,
},
}
out, err := cmd.CombinedOutput()
if err != nil {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: %v: %v", cmd, err)
}
t.Fatalf("Cmd failed with err %v, output: %s", err, out)
}
strOut := strings.TrimSpace(string(out))
t.Logf("id: %s", strOut)
expected := "uid=0(root) gid=0(root)"
// Just check prefix because some distros reportedly output a
// context parameter; see https://golang.org/issue/16224.
// Alpine does not output groups; see https://golang.org/issue/19938.
if !strings.HasPrefix(strOut, expected) {
t.Errorf("expected prefix: %q", expected)
}
}
func TestGroupCleanupUserNamespace(t *testing.T) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
testenv.MustHaveExecPath(t, "id")
cmd := testenv.Command(t, "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 {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: %v: %v", cmd, err)
}
t.Fatalf("Cmd failed with err %v, output: %s", err, out)
}
strOut := strings.TrimSpace(string(out))
t.Logf("id: %s", strOut)
// As in TestGroupCleanup, just check prefix.
// The actual groups and contexts seem to vary from one distro to the next.
expected := "uid=0(root) gid=0(root) groups=0(root)"
if !strings.HasPrefix(strOut, expected) {
t.Errorf("expected prefix: %q", expected)
}
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
// Test for https://go.dev/issue/19661: unshare fails because systemd
// has forced / to be shared
func TestUnshareMountNameSpace(t *testing.T) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
testenv.MustHaveExec(t)
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
dir := flag.Args()[0]
err := syscall.Mount("none", dir, "proc", 0, "")
if err != nil {
fmt.Fprintf(os.Stderr, "unshare: mount %v failed: %#v", dir, err)
os.Exit(2)
}
os.Exit(0)
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
exe, err := os.Executable()
if err != nil {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Fatal(err)
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
d := t.TempDir()
t.Cleanup(func() {
// If the subprocess fails to unshare the parent directory, force-unmount it
// so that the test can clean it up.
if _, err := os.Stat(d); err == nil {
syscall.Unmount(d, syscall.MNT_FORCE)
}
})
cmd := testenv.Command(t, exe, "-test.run=^TestUnshareMountNameSpace$", d)
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
cmd.SysProcAttr = &syscall.SysProcAttr{Unshareflags: syscall.CLONE_NEWNS}
o, err := cmd.CombinedOutput()
if err != nil {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: could not start process with CLONE_NEWNS: %v", err)
}
if testing.Short() && testenv.Builder() != "" && os.Getenv("USER") == "swarming" {
// The Go build system's swarming user is known not to support
// starting a process with CLONE_NEWNS.
// Unfortunately, it doesn't get recognized as such due the current
// implementation of a no-network check using 'unshare -n -r'.
// Since this test does need start this process, we need to skip it.
t.Skipf("skipping: could not start process with CLONE_NEWNS: %v", err)
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Fatalf("unshare failed: %v\n%s", err, o)
}
// How do we tell if the namespace was really unshared? It turns out
// to be simple: just try to remove the directory. If it's still mounted
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
// on the rm will fail with EBUSY.
if err := os.Remove(d); err != nil {
t.Errorf("rmdir failed on %v: %v", d, err)
}
}
// Test for Issue 20103: unshare fails when chroot is used
func TestUnshareMountNameSpaceChroot(t *testing.T) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
dir := flag.Args()[0]
err := syscall.Mount("none", dir, "proc", 0, "")
if err != nil {
fmt.Fprintf(os.Stderr, "unshare: mount %v failed: %#v", dir, err)
os.Exit(2)
}
os.Exit(0)
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
d := t.TempDir()
// Since we are doing a chroot, we need the binary there,
// and it must be statically linked.
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
testenv.MustHaveGoBuild(t)
if platform.MustLinkExternal(runtime.GOOS, runtime.GOARCH, false) {
t.Skipf("skipping: can't build static binary because %s/%s requires external linking", runtime.GOOS, runtime.GOARCH)
}
x := filepath.Join(d, "syscall.test")
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Cleanup(func() {
// If the subprocess fails to unshare the parent directory, force-unmount it
// so that the test can clean it up.
if _, err := os.Stat(d); err == nil {
syscall.Unmount(d, syscall.MNT_FORCE)
}
})
cmd := testenv.Command(t, testenv.GoToolPath(t), "test", "-c", "-o", x, "syscall")
cmd.Env = append(cmd.Environ(), "CGO_ENABLED=0")
if o, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("%v: %v\n%s", cmd, err, o)
}
cmd = testenv.Command(t, "/syscall.test", "-test.run=^TestUnshareMountNameSpaceChroot$", "/")
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
cmd.SysProcAttr = &syscall.SysProcAttr{Chroot: d, Unshareflags: syscall.CLONE_NEWNS}
o, err := cmd.CombinedOutput()
if err != nil {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: could not start process with CLONE_NEWNS and Chroot %q: %v", d, err)
}
if testing.Short() && testenv.Builder() != "" && os.Getenv("USER") == "swarming" {
// The Go build system's swarming user is known not to support
// starting a process with CLONE_NEWNS and Chroot.
// Unfortunately, it doesn't get recognized as such due the current
// implementation of a no-network check using 'unshare -n -r'.
// Since this test does need start this process, we need to skip it.
t.Skipf("skipping: could not start process with CLONE_NEWNS and Chroot %q: %v", d, err)
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Fatalf("unshare failed: %v\n%s", err, o)
}
// How do we tell if the namespace was really unshared? It turns out
// to be simple: just try to remove the executable. If it's still mounted
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
// on, the rm will fail.
if err := os.Remove(x); err != nil {
t.Errorf("rm failed on %v: %v", x, err)
}
if err := os.Remove(d); err != nil {
t.Errorf("rmdir failed on %v: %v", d, err)
}
}
// Test for Issue 29789: unshare fails when uid/gid mapping is specified
func TestUnshareUidGidMapping(t *testing.T) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
defer os.Exit(0)
if err := syscall.Chroot(os.TempDir()); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
}
if os.Getuid() == 0 {
t.Skip("test exercises unprivileged user namespace, fails with privileges")
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
testenv.MustHaveExec(t)
exe, err := os.Executable()
if err != nil {
t.Fatal(err)
}
cmd := testenv.Command(t, exe, "-test.run=^TestUnshareUidGidMapping$")
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
cmd.SysProcAttr = &syscall.SysProcAttr{
Unshareflags: syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER,
GidMappingsEnableSetgroups: false,
UidMappings: []syscall.SysProcIDMap{
{
ContainerID: 0,
HostID: syscall.Getuid(),
Size: 1,
},
},
GidMappings: []syscall.SysProcIDMap{
{
ContainerID: 0,
HostID: syscall.Getgid(),
Size: 1,
},
},
}
out, err := cmd.CombinedOutput()
if err != nil {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: could not start process with CLONE_NEWNS and CLONE_NEWUSER: %v", err)
}
t.Fatalf("Cmd failed with err %v, output: %s", err, out)
}
}
syscall: add CgroupFD support for ForkExec on Linux Implement CLONE_INTO_CGROUP feature, allowing to put a child in a specified cgroup in a clean and simple way. Note that the feature only works for cgroup v2, and requires Linux kernel 5.7 or newer. Using the feature requires a new syscall, clone3. Currently this is the only reason to use clone3, but the code is structured in a way so that other cases may be easily added in the future. Add a test case. While at it, try to simplify the syscall calling code in forkAndExecInChild1, which became complicated over time because: 1. It was using either rawVforkSyscall or RawSyscall6 depending on whether CLONE_NEWUSER was set. 2. On Linux/s390, the first two arguments to clone(2) system call are swapped (which deserved a mention in Linux ABI hall of shame). It was worked around in rawVforkSyscall on s390, but had to be implemented via a switch/case when using RawSyscall6, making the code less clear. Let's - modify rawVforkSyscall to have two arguments (which is also required for clone3); - remove the arguments workaround from s390 asm, instead implementing arguments swap in the caller (which still looks ugly but at least it's done once and is clearly documented now); - use rawVforkSyscall for all cases (since it is essentially similar to RawSyscall6, except for having less parameters, not returning r2, and saving/restoring the return address before/after syscall on 386 and amd64). Updates #51246. Change-Id: Ifcd418ebead9257177338ffbcccd0bdecb94474e Reviewed-on: https://go-review.googlesource.com/c/go/+/417695 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-14 21:18:15 -07:00
func prepareCgroupFD(t *testing.T) (int, string) {
t.Helper()
const O_PATH = 0x200000 // Same for all architectures, but for some reason not defined in syscall for 386||amd64.
// Requires cgroup v2.
const prefix = "/sys/fs/cgroup"
selfCg, err := os.ReadFile("/proc/self/cgroup")
if err != nil {
if os.IsNotExist(err) || os.IsPermission(err) {
t.Skip(err)
}
t.Fatal(err)
}
// Expect a single line like this:
// 0::/user.slice/user-1000.slice/user@1000.service/app.slice/vte-spawn-891992a2-efbb-4f28-aedb-b24f9e706770.scope
// Otherwise it's either cgroup v1 or a hybrid hierarchy.
if bytes.Count(selfCg, []byte("\n")) > 1 {
t.Skip("cgroup v2 not available")
}
cg := bytes.TrimPrefix(selfCg, []byte("0::"))
if len(cg) == len(selfCg) { // No prefix found.
t.Skipf("cgroup v2 not available (/proc/self/cgroup contents: %q)", selfCg)
}
// Need an ability to create a sub-cgroup.
subCgroup, err := os.MkdirTemp(prefix+string(bytes.TrimSpace(cg)), "subcg-")
if err != nil {
// ErrPermission or EROFS (#57262) when running in an unprivileged container.
// ErrNotExist when cgroupfs is not mounted in chroot/schroot.
if os.IsNotExist(err) || testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: %v", err)
syscall: add CgroupFD support for ForkExec on Linux Implement CLONE_INTO_CGROUP feature, allowing to put a child in a specified cgroup in a clean and simple way. Note that the feature only works for cgroup v2, and requires Linux kernel 5.7 or newer. Using the feature requires a new syscall, clone3. Currently this is the only reason to use clone3, but the code is structured in a way so that other cases may be easily added in the future. Add a test case. While at it, try to simplify the syscall calling code in forkAndExecInChild1, which became complicated over time because: 1. It was using either rawVforkSyscall or RawSyscall6 depending on whether CLONE_NEWUSER was set. 2. On Linux/s390, the first two arguments to clone(2) system call are swapped (which deserved a mention in Linux ABI hall of shame). It was worked around in rawVforkSyscall on s390, but had to be implemented via a switch/case when using RawSyscall6, making the code less clear. Let's - modify rawVforkSyscall to have two arguments (which is also required for clone3); - remove the arguments workaround from s390 asm, instead implementing arguments swap in the caller (which still looks ugly but at least it's done once and is clearly documented now); - use rawVforkSyscall for all cases (since it is essentially similar to RawSyscall6, except for having less parameters, not returning r2, and saving/restoring the return address before/after syscall on 386 and amd64). Updates #51246. Change-Id: Ifcd418ebead9257177338ffbcccd0bdecb94474e Reviewed-on: https://go-review.googlesource.com/c/go/+/417695 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-14 21:18:15 -07:00
}
t.Fatal(err)
}
t.Cleanup(func() { syscall.Rmdir(subCgroup) })
cgroupFD, err := syscall.Open(subCgroup, O_PATH, 0)
if err != nil {
t.Fatal(&os.PathError{Op: "open", Path: subCgroup, Err: err})
}
t.Cleanup(func() { syscall.Close(cgroupFD) })
return cgroupFD, "/" + path.Base(subCgroup)
}
func TestUseCgroupFD(t *testing.T) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
testenv.MustHaveExec(t)
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
// Read and print own cgroup path.
selfCg, err := os.ReadFile("/proc/self/cgroup")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
fmt.Print(string(selfCg))
os.Exit(0)
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
exe, err := os.Executable()
if err != nil {
t.Fatal(err)
}
syscall: add CgroupFD support for ForkExec on Linux Implement CLONE_INTO_CGROUP feature, allowing to put a child in a specified cgroup in a clean and simple way. Note that the feature only works for cgroup v2, and requires Linux kernel 5.7 or newer. Using the feature requires a new syscall, clone3. Currently this is the only reason to use clone3, but the code is structured in a way so that other cases may be easily added in the future. Add a test case. While at it, try to simplify the syscall calling code in forkAndExecInChild1, which became complicated over time because: 1. It was using either rawVforkSyscall or RawSyscall6 depending on whether CLONE_NEWUSER was set. 2. On Linux/s390, the first two arguments to clone(2) system call are swapped (which deserved a mention in Linux ABI hall of shame). It was worked around in rawVforkSyscall on s390, but had to be implemented via a switch/case when using RawSyscall6, making the code less clear. Let's - modify rawVforkSyscall to have two arguments (which is also required for clone3); - remove the arguments workaround from s390 asm, instead implementing arguments swap in the caller (which still looks ugly but at least it's done once and is clearly documented now); - use rawVforkSyscall for all cases (since it is essentially similar to RawSyscall6, except for having less parameters, not returning r2, and saving/restoring the return address before/after syscall on 386 and amd64). Updates #51246. Change-Id: Ifcd418ebead9257177338ffbcccd0bdecb94474e Reviewed-on: https://go-review.googlesource.com/c/go/+/417695 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-14 21:18:15 -07:00
fd, suffix := prepareCgroupFD(t)
cmd := testenv.Command(t, exe, "-test.run=^TestUseCgroupFD$")
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
syscall: add CgroupFD support for ForkExec on Linux Implement CLONE_INTO_CGROUP feature, allowing to put a child in a specified cgroup in a clean and simple way. Note that the feature only works for cgroup v2, and requires Linux kernel 5.7 or newer. Using the feature requires a new syscall, clone3. Currently this is the only reason to use clone3, but the code is structured in a way so that other cases may be easily added in the future. Add a test case. While at it, try to simplify the syscall calling code in forkAndExecInChild1, which became complicated over time because: 1. It was using either rawVforkSyscall or RawSyscall6 depending on whether CLONE_NEWUSER was set. 2. On Linux/s390, the first two arguments to clone(2) system call are swapped (which deserved a mention in Linux ABI hall of shame). It was worked around in rawVforkSyscall on s390, but had to be implemented via a switch/case when using RawSyscall6, making the code less clear. Let's - modify rawVforkSyscall to have two arguments (which is also required for clone3); - remove the arguments workaround from s390 asm, instead implementing arguments swap in the caller (which still looks ugly but at least it's done once and is clearly documented now); - use rawVforkSyscall for all cases (since it is essentially similar to RawSyscall6, except for having less parameters, not returning r2, and saving/restoring the return address before/after syscall on 386 and amd64). Updates #51246. Change-Id: Ifcd418ebead9257177338ffbcccd0bdecb94474e Reviewed-on: https://go-review.googlesource.com/c/go/+/417695 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-14 21:18:15 -07:00
cmd.SysProcAttr = &syscall.SysProcAttr{
UseCgroupFD: true,
CgroupFD: fd,
}
out, err := cmd.CombinedOutput()
if err != nil {
if testenv.SyscallIsNotSupported(err) && !errors.Is(err, syscall.EINVAL) {
// Can be one of:
// - clone3 not supported (old kernel);
// - clone3 not allowed (by e.g. seccomp);
// - lack of CAP_SYS_ADMIN.
t.Skipf("clone3 with CLONE_INTO_CGROUP not available: %v", err)
}
syscall: add CgroupFD support for ForkExec on Linux Implement CLONE_INTO_CGROUP feature, allowing to put a child in a specified cgroup in a clean and simple way. Note that the feature only works for cgroup v2, and requires Linux kernel 5.7 or newer. Using the feature requires a new syscall, clone3. Currently this is the only reason to use clone3, but the code is structured in a way so that other cases may be easily added in the future. Add a test case. While at it, try to simplify the syscall calling code in forkAndExecInChild1, which became complicated over time because: 1. It was using either rawVforkSyscall or RawSyscall6 depending on whether CLONE_NEWUSER was set. 2. On Linux/s390, the first two arguments to clone(2) system call are swapped (which deserved a mention in Linux ABI hall of shame). It was worked around in rawVforkSyscall on s390, but had to be implemented via a switch/case when using RawSyscall6, making the code less clear. Let's - modify rawVforkSyscall to have two arguments (which is also required for clone3); - remove the arguments workaround from s390 asm, instead implementing arguments swap in the caller (which still looks ugly but at least it's done once and is clearly documented now); - use rawVforkSyscall for all cases (since it is essentially similar to RawSyscall6, except for having less parameters, not returning r2, and saving/restoring the return address before/after syscall on 386 and amd64). Updates #51246. Change-Id: Ifcd418ebead9257177338ffbcccd0bdecb94474e Reviewed-on: https://go-review.googlesource.com/c/go/+/417695 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Kirill Kolyshkin <kolyshkin@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-14 21:18:15 -07:00
t.Fatalf("Cmd failed with err %v, output: %s", err, out)
}
// NB: this wouldn't work with cgroupns.
if !bytes.HasSuffix(bytes.TrimSpace(out), []byte(suffix)) {
t.Fatalf("got: %q, want: a line that ends with %q", out, suffix)
}
}
func TestCloneTimeNamespace(t *testing.T) {
testenv.MustHaveExec(t)
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
timens, err := os.Readlink("/proc/self/ns/time")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
fmt.Print(string(timens))
os.Exit(0)
}
exe, err := os.Executable()
if err != nil {
t.Fatal(err)
}
cmd := testenv.Command(t, exe, "-test.run=^TestCloneTimeNamespace$")
cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWTIME,
}
out, err := cmd.CombinedOutput()
if err != nil {
if testenv.SyscallIsNotSupported(err) {
// CLONE_NEWTIME does not appear to be supported.
t.Skipf("skipping, CLONE_NEWTIME not supported: %v", err)
}
t.Fatalf("Cmd failed with err %v, output: %s", err, out)
}
// Inode number of the time namespaces should be different.
// Based on https://man7.org/linux/man-pages/man7/time_namespaces.7.html#EXAMPLES
timens, err := os.Readlink("/proc/self/ns/time")
if err != nil {
t.Fatal(err)
}
parentTimeNS := string(timens)
childTimeNS := string(out)
if childTimeNS == parentTimeNS {
t.Fatalf("expected child time namespace to be different from parent time namespace: %s", parentTimeNS)
}
}
type capHeader struct {
version uint32
pid int32
}
type capData struct {
effective uint32
permitted uint32
inheritable uint32
}
const CAP_SYS_TIME = 25
const CAP_SYSLOG = 34
type caps struct {
hdr capHeader
data [2]capData
}
func getCaps() (caps, error) {
var c caps
// Get capability version
if _, _, errno := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(&c.hdr)), uintptr(unsafe.Pointer(nil)), 0); errno != 0 {
return c, fmt.Errorf("SYS_CAPGET: %v", errno)
}
// Get current capabilities
if _, _, errno := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(&c.hdr)), uintptr(unsafe.Pointer(&c.data[0])), 0); errno != 0 {
return c, fmt.Errorf("SYS_CAPGET: %v", errno)
}
return c, nil
}
func TestAmbientCaps(t *testing.T) {
testAmbientCaps(t, false)
}
func TestAmbientCapsUserns(t *testing.T) {
testAmbientCaps(t, true)
}
func testAmbientCaps(t *testing.T, userns bool) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
caps, err := getCaps()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
}
if caps.data[0].effective&(1<<uint(CAP_SYS_TIME)) == 0 {
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)
}
os.Exit(0)
}
// skip on android, due to lack of lookup support
if runtime.GOOS == "android" {
t.Skip("skipping test on android; see Issue 27327")
}
u, err := user.Lookup("nobody")
if err != nil {
t.Fatal(err)
}
uid, err := strconv.ParseInt(u.Uid, 0, 32)
if err != nil {
t.Fatal(err)
}
gid, err := strconv.ParseInt(u.Gid, 0, 32)
if err != nil {
t.Fatal(err)
}
// Copy the test binary to a temporary location which is readable by nobody.
f, err := os.CreateTemp("", "gotest")
if err != nil {
t.Fatal(err)
}
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Cleanup(func() {
f.Close()
os.Remove(f.Name())
})
testenv.MustHaveExec(t)
exe, err := os.Executable()
if err != nil {
t.Fatal(err)
}
e, err := os.Open(exe)
if err != nil {
t.Fatal(err)
}
defer e.Close()
if _, err := io.Copy(f, e); err != nil {
t.Fatal(err)
}
if err := f.Chmod(0755); err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}
cmd := testenv.Command(t, f.Name(), "-test.run=^"+t.Name()+"$")
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uint32(uid),
Gid: uint32(gid),
},
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 {
if testenv.SyscallIsNotSupported(err) {
syscall: avoid making assumptions about syscall permissions We currently check for at least three different permission bits before running tests that require root permissions: we look for UID 0, lack of an LXC container, and lack of a Docker container, and probe a number of distro-specific files in /proc and /sys. The sheer number of these checks suggests that we have probably missed at least one. Per Alan J. Perlis, “If you have a procedure with ten parameters, you probably missed some.” (And, indeed, we definitely have: a Debian patch¹ adds one more environment check!) CL 58170 added some of these container checks, but “decided to go this way instead of just skipping os.IsPermission errors because many of those tests were specifically written to check false positive permission errors.” However, we can't in general distinguish between a false-positive error and a real one caused by a container: if one is making a change to the syscall package, they should run the tests with -v and check for unexpected skips. Notably: - TestUnshare already skips itself if the command fails with an error ending in the string "operation not permitted", which could be caused by a variety of possible bugs. - The Unshare tests added in CL 38471 will fail with a permission error if CLONE_NEWNS is not supported, but it seems to me that if CLONE_NEWNS is supported — sufficient to start the process! — then Unmount must also be supported, and the test can at least check that the two are consistent. - The AmbientCaps tests should fail to start the subprocess with EINVAL or similar (not produce bogus output) if the kernel does not support ambient caps for any reason, which we can then detect. (If the subprocess fails in the way the test is concerned about, it will exit with status 2, not fail to start in the first place.) By executing the system calls and checking for permission errors, this change exposed an existing bug for AmbientCaps (filed as #57208), which was detected by the linux-arm-aws builder. For #57208. Updates #21379. Updates #14693. ¹https://sources.debian.org/patches/golang-1.19/1.19.3-1/0006-skip-userns-test-in-schroot-as-well.patch/ Change-Id: I9b167661fa1bb823168c8b50d8bbbf9643e49f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/456375 Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Alexander Morozov <lk4d4math@gmail.com> Run-TryBot: Bryan Mills <bcmills@google.com>
2022-12-08 15:23:32 -05:00
t.Skipf("skipping: %v: %v", cmd, err)
}
t.Fatal(err.Error())
}
}