diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-10-03 18:46:38 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-10-03 18:52:11 +0900 |
| commit | f2e188c4a0f472bcbd87189f63099d2c73936789 (patch) | |
| tree | 1b96bd5bb8ae99460d93e6d477e5ee024a08b009 /test/internal/sandbox | |
| parent | aa41002e8078a3ab00896cbd403e573c6dd817c2 (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.go | 40 | ||||
| -rw-r--r-- | test/internal/sandbox/ptrace.go | 87 | ||||
| -rw-r--r-- | test/internal/sandbox/seccomp.go | 2 |
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 |
