From 6e82d8f930878d2748862ba89e511589349d9c85 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Fri, 28 Mar 2025 01:09:26 +0900 Subject: [PATCH] test/sandbox/ptrace: dump seccomp bpf program Signed-off-by: Ophestra --- test/sandbox/ptrace.go | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 test/sandbox/ptrace.go diff --git a/test/sandbox/ptrace.go b/test/sandbox/ptrace.go new file mode 100644 index 0000000..391c8c7 --- /dev/null +++ b/test/sandbox/ptrace.go @@ -0,0 +1,115 @@ +package sandbox + +import ( + "bufio" + "fmt" + "io" + "os" + "strings" + "syscall" + "time" + "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 { + const ( + statePrefix = "State:" + stateSuffix = "t (tracing stop)" + ) + + var r io.ReadSeekCloser + if f, err := os.Open(fmt.Sprintf("/proc/%d/status", pid)); err != nil { + return err + } else { + r = f + } + + if _, errno := ptrace(PTRACE_ATTACH, pid, 0, nil); errno != 0 { + return &ptraceError{"PTRACE_ATTACH", errno} + } + + // ugly! but there does not appear to be another way + for { + time.Sleep(10 * time.Millisecond) + + if _, err := r.Seek(0, io.SeekStart); err != nil { + return err + } + s := bufio.NewScanner(r) + + var found bool + for s.Scan() { + found = strings.HasPrefix(s.Text(), statePrefix) + if found { + break + } + } + if err := s.Err(); err != nil { + return err + } + + if !found { + return syscall.EBADE + } + + if strings.HasSuffix(s.Text(), stateSuffix) { + 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(pid, index int) ([]sockFilter, error) { + var buf []sockFilter + if n, errno := ptrace(PTRACE_SECCOMP_GET_FILTER, pid, index, nil); errno != 0 { + return nil, &ptraceError{"PTRACE_SECCOMP_GET_FILTER", errno} + } else { + buf = make([]sockFilter, 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 +}