Source file src/syscall/exec_freebsd_test.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build freebsd
     6  
     7  package syscall_test
     8  
     9  import (
    10  	"fmt"
    11  	"internal/testenv"
    12  	"os"
    13  	"os/exec"
    14  	"path/filepath"
    15  	"syscall"
    16  	"testing"
    17  	"unsafe"
    18  )
    19  
    20  const (
    21  	flagJailCreate = uintptr(0x1)
    22  )
    23  
    24  func prepareJail(t *testing.T) (int, string) {
    25  	t.Helper()
    26  
    27  	root := t.TempDir()
    28  	paramPath := []byte("path\x00")
    29  	conf := make([]syscall.Iovec, 4)
    30  	conf[0].Base = &paramPath[0]
    31  	conf[0].SetLen(len(paramPath))
    32  	p, err := syscall.BytePtrFromString(root)
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  	conf[1].Base = p
    37  	conf[1].SetLen(len(root) + 1)
    38  
    39  	paramPersist := []byte("persist\x00")
    40  	conf[2].Base = &paramPersist[0]
    41  	conf[2].SetLen(len(paramPersist))
    42  	conf[3].Base = nil
    43  	conf[3].SetLen(0)
    44  
    45  	id, _, err1 := syscall.Syscall(syscall.SYS_JAIL_SET,
    46  		uintptr(unsafe.Pointer(&conf[0])), uintptr(len(conf)), flagJailCreate)
    47  	if err1 != 0 {
    48  		t.Fatalf("jail_set: %v", err1)
    49  	}
    50  	t.Cleanup(func() {
    51  		_, _, err1 := syscall.Syscall(syscall.SYS_JAIL_REMOVE, id, 0, 0)
    52  		if err1 != 0 {
    53  			t.Errorf("failed to cleanup jail: %v", err)
    54  		}
    55  	})
    56  
    57  	return int(id), root
    58  }
    59  
    60  func TestJailAttach(t *testing.T) {
    61  	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
    62  		jailed, err := syscall.SysctlUint32("security.jail.jailed")
    63  		if err != nil {
    64  			fmt.Fprintln(os.Stderr, err)
    65  			os.Exit(2)
    66  		}
    67  		if jailed != 1 {
    68  			t.Fatalf("jailed = %d, want 1", jailed)
    69  		}
    70  		return
    71  	}
    72  
    73  	testenv.MustHaveGoBuild(t)
    74  	// Make sure we are running as root, so we have permissions to create
    75  	// and remove jails.
    76  	if os.Getuid() != 0 {
    77  		t.Skip("kernel prohibits jail system calls in unprivileged process")
    78  	}
    79  
    80  	jid, root := prepareJail(t)
    81  
    82  	// Since jail attach does an implicit chroot to the jail's path,
    83  	// we need the binary there, and it must be statically linked.
    84  	x := filepath.Join(root, "syscall.test")
    85  	cmd := exec.Command(testenv.GoToolPath(t), "test", "-c", "-o", x, "syscall")
    86  	cmd.Env = append(os.Environ(), "CGO_ENABLED=0")
    87  	if o, err := cmd.CombinedOutput(); err != nil {
    88  		t.Fatalf("Build of syscall in jail root failed, output %v, err %v", o, err)
    89  	}
    90  
    91  	cmd = exec.Command("/syscall.test", "-test.run=TestJailAttach", "/")
    92  	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
    93  	cmd.SysProcAttr = &syscall.SysProcAttr{Jail: jid}
    94  	out, err := cmd.CombinedOutput()
    95  	if err != nil {
    96  		t.Fatalf("Cmd failed with err %v, output: %s", err, out)
    97  	}
    98  }
    99  

View as plain text