aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-03-28 01:09:26 +0900
committerOphestra <cat@gensokyo.uk>2025-03-28 01:35:56 +0900
commit660a2898dc0dbfe9963d8f336e04582955b56b8a (patch)
treeee6dee579efb593c04950f481270be81a6ea1a19 /test
parentfaf59e12c09348de3fe6a6f491efcdc820ef93d1 (diff)
test/sandbox/ptrace: dump seccomp bpf program
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'test')
-rw-r--r--test/sandbox/assert.go2
-rw-r--r--test/sandbox/ptrace.go115
-rw-r--r--test/sandbox/seccomp.go4
3 files changed, 117 insertions, 4 deletions
diff --git a/test/sandbox/assert.go b/test/sandbox/assert.go
index 3a34c736..c4b59fd7 100644
--- a/test/sandbox/assert.go
+++ b/test/sandbox/assert.go
@@ -116,7 +116,7 @@ func (t *T) MustCheck(want *TestCase) {
}
if want.Seccomp {
- if TrySyscalls() != nil {
+ if trySyscalls() != nil {
os.Exit(1)
}
} else {
diff --git a/test/sandbox/ptrace.go b/test/sandbox/ptrace.go
new file mode 100644
index 00000000..391c8c79
--- /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
+}
diff --git a/test/sandbox/seccomp.go b/test/sandbox/seccomp.go
index 9ccf1348..437679c4 100644
--- a/test/sandbox/seccomp.go
+++ b/test/sandbox/seccomp.go
@@ -10,9 +10,7 @@ import (
*/
import "C"
-const NULL = 0
-
-func TrySyscalls() error {
+func trySyscalls() error {
testCases := []struct {
name string
errno syscall.Errno