From fba201c9953a490da914b09e09eaaa697a4b36e1 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 5 Nov 2025 06:00:39 +0900 Subject: container/std: relocate rule types This enables its use in hst for #15. Signed-off-by: Ophestra --- container/seccomp/libseccomp.go | 70 +++++++++++---------------------------- container/seccomp/std_test.go | 63 +++++++++++++++++++++++++++++++++++ container/seccomp/syscall_test.go | 63 ----------------------------------- 3 files changed, 82 insertions(+), 114 deletions(-) create mode 100644 container/seccomp/std_test.go delete mode 100644 container/seccomp/syscall_test.go (limited to 'container/seccomp') diff --git a/container/seccomp/libseccomp.go b/container/seccomp/libseccomp.go index c3550291..962d6844 100644 --- a/container/seccomp/libseccomp.go +++ b/container/seccomp/libseccomp.go @@ -14,6 +14,8 @@ import ( "runtime/cgo" "syscall" "unsafe" + + "hakurei.app/container/std" ) // ErrInvalidRules is returned for a zero-length rules slice. @@ -54,31 +56,12 @@ func (e *LibraryError) Is(err error) bool { } type ( - // scmpUint is equivalent to [ScmpUint]. + // scmpUint is equivalent to [std.ScmpUint]. scmpUint = C.uint - // ScmpUint is equivalent to C.uint. - ScmpUint uint32 - // scmpInt is equivalent to [ScmpInt]. + // scmpInt is equivalent to [std.ScmpInt]. scmpInt = C.int - // ScmpInt is equivalent to C.int. - ScmpInt int32 - - // ScmpSyscall represents a syscall number passed to libseccomp via [NativeRule.Syscall]. - ScmpSyscall ScmpInt - // ScmpErrno represents an errno value passed to libseccomp via [NativeRule.Errno]. - ScmpErrno ScmpInt - - // A NativeRule specifies an arch-specific action taken by seccomp under certain conditions. - NativeRule struct { - // Syscall is the arch-dependent syscall number to act against. - Syscall ScmpSyscall - // Errno is the errno value to return when the condition is satisfied. - Errno ScmpErrno - // Arg is the optional struct scmp_arg_cmp passed to libseccomp. - Arg *ScmpArgCmp - } - // syscallRule is equivalent to [NativeRule]. + // syscallRule is equivalent to [std.NativeRule]. syscallRule = C.struct_hakurei_syscall_rule ) @@ -115,9 +98,9 @@ func hakurei_scmp_allocate(f C.uintptr_t, len C.size_t) (buf unsafe.Pointer) { return cgo.Handle(f).Value().(cbAllocateBuffer)(len) } -// makeFilter generates a bpf program from a slice of [NativeRule] and writes the resulting byte slice to p. +// makeFilter generates a bpf program from a slice of [std.NativeRule] and writes the resulting byte slice to p. // The filter is installed to the current process if p is nil. -func makeFilter(rules []NativeRule, flags ExportFlag, p *[]byte) error { +func makeFilter(rules []std.NativeRule, flags ExportFlag, p *[]byte) error { if len(rules) == 0 { return ErrInvalidRules } @@ -180,22 +163,26 @@ func makeFilter(rules []NativeRule, flags ExportFlag, p *[]byte) error { return err } -// Export generates a bpf program from a slice of [NativeRule]. +// Export generates a bpf program from a slice of [std.NativeRule]. // Errors returned by libseccomp is wrapped in [LibraryError]. -func Export(rules []NativeRule, flags ExportFlag) (data []byte, err error) { +func Export(rules []std.NativeRule, flags ExportFlag) (data []byte, err error) { err = makeFilter(rules, flags, &data) return } -// Load generates a bpf program from a slice of [NativeRule] and enforces it on the current process. +// Load generates a bpf program from a slice of [std.NativeRule] and enforces it on the current process. // Errors returned by libseccomp is wrapped in [LibraryError]. -func Load(rules []NativeRule, flags ExportFlag) error { return makeFilter(rules, flags, nil) } +func Load(rules []std.NativeRule, flags ExportFlag) error { return makeFilter(rules, flags, nil) } type ( // Comparison operators. scmpCompare = C.enum_scmp_compare - // ScmpCompare is equivalent to enum scmp_compare; - ScmpCompare ScmpUint + + // Argument datum. + scmpDatum = C.scmp_datum_t + + // Argument / Value comparison definition. + scmpArgCmp = C.struct_scmp_arg_cmp ) const ( @@ -219,29 +206,10 @@ const ( _SCMP_CMP_MAX = C._SCMP_CMP_MAX ) -type ( - // Argument datum. - scmpDatum = C.scmp_datum_t - // ScmpDatum is equivalent to scmp_datum_t. - ScmpDatum uint64 - - // Argument / Value comparison definition. - scmpArgCmp = C.struct_scmp_arg_cmp - // ScmpArgCmp is equivalent to struct scmp_arg_cmp. - ScmpArgCmp struct { - // argument number, starting at 0 - Arg ScmpUint - // the comparison op, e.g. SCMP_CMP_* - Op ScmpCompare - - DatumA, DatumB ScmpDatum - } -) - const ( - // PersonaLinux is passed in a [ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY. + // PersonaLinux is passed in a [std.ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY. PersonaLinux = C.PER_LINUX - // PersonaLinux32 is passed in a [ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY. + // PersonaLinux32 is passed in a [std.ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY. PersonaLinux32 = C.PER_LINUX32 ) diff --git a/container/seccomp/std_test.go b/container/seccomp/std_test.go new file mode 100644 index 00000000..438a5e3b --- /dev/null +++ b/container/seccomp/std_test.go @@ -0,0 +1,63 @@ +package seccomp + +import ( + "reflect" + "testing" + "unsafe" + + "hakurei.app/container/std" +) + +func TestSyscallResolveName(t *testing.T) { + t.Parallel() + + for name, want := range std.Syscalls() { + t.Run(name, func(t *testing.T) { + t.Parallel() + + // this checks the std implementation against libseccomp. + if got, ok := syscallResolveName(name); !ok || got != want { + t.Errorf("syscallResolveName(%q) = %d, want %d", name, got, want) + } + }) + } +} + +func TestRuleType(t *testing.T) { + assertKind[std.ScmpUint, scmpUint](t) + assertKind[std.ScmpInt, scmpInt](t) + + assertSize[std.NativeRule, syscallRule](t) + assertKind[std.ScmpDatum, scmpDatum](t) + assertKind[std.ScmpCompare, scmpCompare](t) + assertSize[std.ScmpArgCmp, scmpArgCmp](t) +} + +// assertSize asserts that native and equivalent are of the same size. +func assertSize[native, equivalent any](t *testing.T) { + t.Helper() + + got, want := unsafe.Sizeof(*new(native)), unsafe.Sizeof(*new(equivalent)) + if got != want { + t.Fatalf("%s: %d, want %d", reflect.TypeFor[native]().Name(), got, want) + } +} + +// assertKind asserts that native and equivalent are of the same kind. +func assertKind[native, equivalent any](t *testing.T) { + t.Helper() + + assertSize[native, equivalent](t) + nativeType, equivalentType := reflect.TypeFor[native](), reflect.TypeFor[equivalent]() + got, want := nativeType.Kind(), equivalentType.Kind() + + if got == reflect.Invalid || want == reflect.Invalid { + t.Fatalf("%s: invalid call to assertKind", nativeType.Name()) + } + if got == reflect.Struct { + t.Fatalf("%s: struct is unsupported by assertKind", nativeType.Name()) + } + if got != want { + t.Fatalf("%s: %s, want %s", nativeType.Name(), nativeType.Kind(), equivalentType.Kind()) + } +} diff --git a/container/seccomp/syscall_test.go b/container/seccomp/syscall_test.go deleted file mode 100644 index 98076cf3..00000000 --- a/container/seccomp/syscall_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package seccomp - -import ( - "reflect" - "testing" - "unsafe" - - "hakurei.app/container/std" -) - -func TestSyscallResolveName(t *testing.T) { - t.Parallel() - - for name, want := range std.Syscalls() { - t.Run(name, func(t *testing.T) { - t.Parallel() - - // this checks the std implementation against libseccomp. - if got, ok := syscallResolveName(name); !ok || got != want { - t.Errorf("syscallResolveName(%q) = %d, want %d", name, got, want) - } - }) - } -} - -func TestRuleType(t *testing.T) { - assertKind[ScmpUint, scmpUint](t) - assertKind[ScmpInt, scmpInt](t) - - assertSize[NativeRule, syscallRule](t) - assertKind[ScmpDatum, scmpDatum](t) - assertKind[ScmpCompare, scmpCompare](t) - assertSize[ScmpArgCmp, scmpArgCmp](t) -} - -// assertSize asserts that native and equivalent are of the same size. -func assertSize[native, equivalent any](t *testing.T) { - t.Helper() - - got, want := unsafe.Sizeof(*new(native)), unsafe.Sizeof(*new(equivalent)) - if got != want { - t.Fatalf("%s: %d, want %d", reflect.TypeFor[native]().Name(), got, want) - } -} - -// assertKind asserts that native and equivalent are of the same kind. -func assertKind[native, equivalent any](t *testing.T) { - t.Helper() - - assertSize[native, equivalent](t) - nativeType, equivalentType := reflect.TypeFor[native](), reflect.TypeFor[equivalent]() - got, want := nativeType.Kind(), equivalentType.Kind() - - if got == reflect.Invalid || want == reflect.Invalid { - t.Fatalf("%s: invalid call to assertKind", nativeType.Name()) - } - if got == reflect.Struct { - t.Fatalf("%s: struct is unsupported by assertKind", nativeType.Name()) - } - if got != want { - t.Fatalf("%s: %s, want %s", nativeType.Name(), nativeType.Kind(), equivalentType.Kind()) - } -} -- cgit v1.3.1