]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: add Unshare flags to SysProcAttr on Linux
authorJess Frazelle <me@jessfraz.com>
Thu, 19 May 2016 01:47:24 +0000 (18:47 -0700)
committerIan Lance Taylor <iant@golang.org>
Fri, 20 May 2016 00:51:46 +0000 (00:51 +0000)
This patch adds Unshare flags to SysProcAttr for Linux systems.

Fixes #1954

Change-Id: Id819c3f92b1474e5a06dd8d55f89d74a43eb770c
Reviewed-on: https://go-review.googlesource.com/23233
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/syscall/exec_linux.go
src/syscall/exec_linux_test.go

index e49bad75b284ff3bdd08646317868cb508020f5f..5a6b2049970901165ab500b2606699ed03386763 100644 (file)
@@ -32,6 +32,7 @@ type SysProcAttr struct {
        Pgid        int            // Child's process group ID if Setpgid.
        Pdeathsig   Signal         // Signal that the process will get when its parent dies (Linux only)
        Cloneflags  uintptr        // Flags for clone calls (Linux only)
+       Unshare     uintptr        // Flags for unshare calls (Linux only)
        UidMappings []SysProcIDMap // User ID mappings for user namespaces.
        GidMappings []SysProcIDMap // Group ID mappings for user namespaces.
        // GidMappingsEnableSetgroups enabling setgroups syscall.
@@ -194,6 +195,14 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
                }
        }
 
+       // Unshare
+       if sys.Unshare != 0 {
+               _, _, err1 = RawSyscall(SYS_UNSHARE, sys.Unshare, 0, 0)
+               if err1 != 0 {
+                       goto childerror
+               }
+       }
+
        // User and groups
        if cred := sys.Credential; cred != nil {
                ngroups := uintptr(len(cred.Groups))
index eb32cfd4b1e46c7299781c64c39afdd66df102b0..ec5be107e049f81eedd76aeb427909d2df49bf10 100644 (file)
@@ -125,3 +125,39 @@ func TestEmptyCredGroupsDisableSetgroups(t *testing.T) {
                t.Fatal(err)
        }
 }
+
+func TestUnshare(t *testing.T) {
+       // Make sure we are running as root so we have permissions to use unshare
+       // and create a network namespace.
+       if os.Getuid() != 0 {
+               t.Skip("kernel prohibits unshare in unprivileged process, unless using user namespace")
+       }
+
+       // When running under the Go continuous build, skip tests for
+       // now when under Kubernetes. (where things are root but not quite)
+       // Both of these are our own environment variables.
+       // See Issue 12815.
+       if os.Getenv("GO_BUILDER_NAME") != "" && os.Getenv("IN_KUBERNETES") == "1" {
+               t.Skip("skipping test on Kubernetes-based builders; see Issue 12815")
+       }
+
+       cmd := exec.Command("ip", "a")
+       cmd.SysProcAttr = &syscall.SysProcAttr{
+               Unshare: syscall.CLONE_NEWNET,
+       }
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               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)
+       }
+
+       lines := strings.Split(sout, "\n")
+       if len(lines) != 2 {
+               t.Fatalf("Expected 2 lines of output, got %d", len(lines))
+       }
+}