aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/internal/sandbox
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-10-03 18:46:38 +0900
committerOphestra <cat@gensokyo.uk>2026-10-03 18:52:11 +0900
commitf2e188c4a0f472bcbd87189f63099d2c73936789 (patch)
tree1b96bd5bb8ae99460d93e6d477e5ee024a08b009 /test/internal/sandbox
parentaa41002e8078a3ab00896cbd403e573c6dd817c2 (diff)
test/internal/testsuite: move ptrace helpers
This also cleans up their API. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'test/internal/sandbox')
-rw-r--r--test/internal/sandbox/assert.go40
-rw-r--r--test/internal/sandbox/ptrace.go87
-rw-r--r--test/internal/sandbox/seccomp.go2
3 files changed, 7 insertions, 122 deletions
diff --git a/test/internal/sandbox/assert.go b/test/internal/sandbox/assert.go
index 2125419b..e2bcc8ae 100644
--- a/test/internal/sandbox/assert.go
+++ b/test/internal/sandbox/assert.go
@@ -9,8 +9,6 @@
package sandbox
import (
- "crypto/sha512"
- "encoding/hex"
"encoding/json"
"errors"
"io/fs"
@@ -21,6 +19,7 @@ import (
"syscall"
"hakurei.app/test/internal/mountinfo"
+ "hakurei.app/test/internal/testsuite"
)
var (
@@ -204,20 +203,20 @@ func (t *T) MustCheck(want *TestCase) {
}
func MustCheckFilter(pid int, want string) {
- err := CheckFilter(pid, want)
+ err := testsuite.CheckFilter(pid, 0, want)
if err == nil {
return
}
- perr, ok := errors.AsType[*ptraceError](err)
+ e, ok := errors.AsType[*os.SyscallError](err)
if !ok {
fatalf("%s", err)
}
- switch perr.op {
+ switch e.Syscall {
case "PTRACE_ATTACH":
fatalf("cannot attach to process %d: %v", pid, err)
case "PTRACE_SECCOMP_GET_FILTER":
- if perr.errno == syscall.ENOENT {
+ if errors.Is(e.Err, syscall.ENOENT) {
fatalf("seccomp filter not installed for process %d", pid)
}
fatalf("cannot get filter: %v", err)
@@ -228,35 +227,6 @@ func MustCheckFilter(pid int, want string) {
*(*int)(nil) = 0 // not reached
}
-func CheckFilter(pid int, want string) error {
- if err := ptraceAttach(pid); err != nil {
- return err
- }
- defer func() {
- if err := ptraceDetach(pid); err != nil {
- printf("cannot detach from process %d: %v", pid, err)
- }
- }()
-
- h := sha512.New()
-
- if buf, err := getFilter[[8]byte](pid, 0); err != nil {
- return err
- } else {
- for _, b := range buf {
- h.Write(b[:])
- }
- }
-
- if got := hex.EncodeToString(h.Sum(nil)); got != want {
- printf("[FAIL] %s", got)
- return syscall.ENOTRECOVERABLE
- } else {
- printf("[ OK ] %s", got)
- return nil
- }
-}
-
func mustDecode(wantFilePath string, v any) {
if f, err := os.Open(wantFilePath); err != nil {
fatalf("cannot open %q: %v", wantFilePath, err)
diff --git a/test/internal/sandbox/ptrace.go b/test/internal/sandbox/ptrace.go
deleted file mode 100644
index 8272ff5b..00000000
--- a/test/internal/sandbox/ptrace.go
+++ /dev/null
@@ -1,87 +0,0 @@
-//go:build testtool
-
-package sandbox
-
-import (
- "errors"
- "fmt"
- "syscall"
- "unsafe"
-)
-
-const (
- NULL = 0
-
- PTRACE_ATTACH = 16
- PTRACE_DETACH = 17
- PTRACE_SECCOMP_GET_FILTER = 0x420c
-)
-
-type ptraceError struct {
- op string
- errno syscall.Errno
-}
-
-func (p *ptraceError) Error() string { return fmt.Sprintf("%s: %v", p.op, p.errno) }
-
-func (p *ptraceError) Unwrap() error {
- if p.errno == 0 {
- return nil
- }
- return p.errno
-}
-
-func ptrace(op uintptr, pid, addr int, data unsafe.Pointer) (r uintptr, errno syscall.Errno) {
- r, _, errno = syscall.Syscall6(syscall.SYS_PTRACE, op, uintptr(pid), uintptr(addr), uintptr(data), NULL, NULL)
- return
-}
-
-func ptraceAttach(pid int) error {
- if _, errno := ptrace(PTRACE_ATTACH, pid, 0, nil); errno != 0 {
- return &ptraceError{"PTRACE_ATTACH", errno}
- }
-
- var status syscall.WaitStatus
- for {
- if _, err := syscall.Wait4(pid, &status, syscall.WALL, nil); err != nil {
- if errors.Is(err, syscall.EINTR) {
- continue
- }
- fatalf("cannot waitpid: %v", err)
- }
- break
- }
-
- return nil
-}
-
-func ptraceDetach(pid int) error {
- if _, errno := ptrace(PTRACE_DETACH, pid, 0, nil); errno != 0 {
- return &ptraceError{"PTRACE_DETACH", errno}
- }
- return nil
-}
-
-type sockFilter struct { /* Filter block */
- code uint16 /* Actual filter code */
- jt uint8 /* Jump true */
- jf uint8 /* Jump false */
- k uint32 /* Generic multiuse field */
-}
-
-func getFilter[T comparable](pid, index int) ([]T, error) {
- if s := unsafe.Sizeof(*new(T)); s != 8 {
- panic(fmt.Sprintf("invalid filter block size %d", s))
- }
-
- var buf []T
- if n, errno := ptrace(PTRACE_SECCOMP_GET_FILTER, pid, index, nil); errno != 0 {
- return nil, &ptraceError{"PTRACE_SECCOMP_GET_FILTER", errno}
- } else {
- buf = make([]T, n)
- }
- if _, errno := ptrace(PTRACE_SECCOMP_GET_FILTER, pid, index, unsafe.Pointer(&buf[0])); errno != 0 {
- return nil, &ptraceError{"PTRACE_SECCOMP_GET_FILTER", errno}
- }
- return buf, nil
-}
diff --git a/test/internal/sandbox/seccomp.go b/test/internal/sandbox/seccomp.go
index 7df781d2..1d8cd457 100644
--- a/test/internal/sandbox/seccomp.go
+++ b/test/internal/sandbox/seccomp.go
@@ -12,6 +12,8 @@ import (
*/
import "C"
+const NULL = 0
+
func trySyscalls() error {
testCases := []struct {
name string