// Copyright 2023 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 freebsd package syscall_test import ( "fmt" "internal/testenv" "os" "os/exec" "path/filepath" "syscall" "testing" "unsafe" ) const ( flagJailCreate = uintptr(0x1) ) func prepareJail(t *testing.T) (int, string) { t.Helper() root := t.TempDir() paramPath := []byte("path\x00") conf := make([]syscall.Iovec, 4) conf[0].Base = ¶mPath[0] conf[0].SetLen(len(paramPath)) p, err := syscall.BytePtrFromString(root) if err != nil { t.Fatal(err) } conf[1].Base = p conf[1].SetLen(len(root) + 1) paramPersist := []byte("persist\x00") conf[2].Base = ¶mPersist[0] conf[2].SetLen(len(paramPersist)) conf[3].Base = nil conf[3].SetLen(0) id, _, err1 := syscall.Syscall(syscall.SYS_JAIL_SET, uintptr(unsafe.Pointer(&conf[0])), uintptr(len(conf)), flagJailCreate) if err1 != 0 { t.Fatalf("jail_set: %v", err1) } t.Cleanup(func() { _, _, err1 := syscall.Syscall(syscall.SYS_JAIL_REMOVE, id, 0, 0) if err1 != 0 { t.Errorf("failed to cleanup jail: %v", err) } }) return int(id), root } func TestJailAttach(t *testing.T) { if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { jailed, err := syscall.SysctlUint32("security.jail.jailed") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(2) } if jailed != 1 { t.Fatalf("jailed = %d, want 1", jailed) } return } testenv.MustHaveGoBuild(t) // Make sure we are running as root, so we have permissions to create // and remove jails. if os.Getuid() != 0 { t.Skip("kernel prohibits jail system calls in unprivileged process") } jid, root := prepareJail(t) // Since jail attach does an implicit chroot to the jail's path, // we need the binary there, and it must be statically linked. x := filepath.Join(root, "syscall.test") cmd := exec.Command(testenv.GoToolPath(t), "test", "-c", "-o", x, "syscall") cmd.Env = append(os.Environ(), "CGO_ENABLED=0") if o, err := cmd.CombinedOutput(); err != nil { t.Fatalf("Build of syscall in jail root failed, output %v, err %v", o, err) } cmd = exec.Command("/syscall.test", "-test.run=TestJailAttach", "/") cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") cmd.SysProcAttr = &syscall.SysProcAttr{Jail: jid} out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("Cmd failed with err %v, output: %s", err, out) } }