All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 1m56s
Test / Sandbox (race detector) (push) Successful in 3m7s
Test / Planterette (push) Successful in 3m35s
Test / Hakurei (race detector) (push) Successful in 4m23s
Test / Hakurei (push) Successful in 2m7s
Test / Flake checks (push) Successful in 1m19s
Filter programs are different across platforms. This representation is also much more readable. Signed-off-by: Ophestra <cat@gensokyo.uk>
94 lines
2.4 KiB
Go
94 lines
2.4 KiB
Go
package seccomp_test
|
|
|
|
import (
|
|
"crypto/sha512"
|
|
"errors"
|
|
"io"
|
|
"slices"
|
|
"syscall"
|
|
"testing"
|
|
|
|
. "hakurei.app/container/seccomp"
|
|
)
|
|
|
|
func TestExport(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
flags ExportFlag
|
|
presets FilterPreset
|
|
wantErr bool
|
|
}{
|
|
{"everything", AllowMultiarch | AllowCAN |
|
|
AllowBluetooth, PresetExt |
|
|
PresetDenyNS | PresetDenyTTY | PresetDenyDevel |
|
|
PresetLinux32, false},
|
|
|
|
{"compat", 0, 0, false},
|
|
{"base", 0, PresetExt, false},
|
|
{"strict", 0, PresetStrict, false},
|
|
{"strict compat", 0, PresetDenyNS | PresetDenyTTY | PresetDenyDevel, false},
|
|
{"hakurei default", 0, PresetExt | PresetDenyDevel, false},
|
|
}
|
|
|
|
buf := make([]byte, 8)
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
e := New(Preset(tc.presets, tc.flags), tc.flags)
|
|
want := bpfExpected[bpfPreset{tc.flags, tc.presets}]
|
|
digest := sha512.New()
|
|
|
|
if _, err := io.CopyBuffer(digest, e, buf); (err != nil) != tc.wantErr {
|
|
t.Errorf("Exporter: error = %v, wantErr %v", err, tc.wantErr)
|
|
return
|
|
}
|
|
if err := e.Close(); err != nil {
|
|
t.Errorf("Close: error = %v", err)
|
|
}
|
|
if got := digest.Sum(nil); !slices.Equal(got, want) {
|
|
t.Fatalf("Export() hash = %x, want %x",
|
|
got, want)
|
|
return
|
|
}
|
|
})
|
|
}
|
|
|
|
t.Run("close without use", func(t *testing.T) {
|
|
e := New(Preset(0, 0), 0)
|
|
if err := e.Close(); !errors.Is(err, syscall.EINVAL) {
|
|
t.Errorf("Close: error = %v", err)
|
|
return
|
|
}
|
|
})
|
|
|
|
t.Run("close partial read", func(t *testing.T) {
|
|
e := New(Preset(0, 0), 0)
|
|
if _, err := e.Read(nil); err != nil {
|
|
t.Errorf("Read: error = %v", err)
|
|
return
|
|
}
|
|
// the underlying implementation uses buffered io, so the outcome of this is nondeterministic;
|
|
// that is not harmful however, so both outcomes are checked for here
|
|
if err := e.Close(); err != nil &&
|
|
(!errors.Is(err, syscall.ECANCELED) || !errors.Is(err, syscall.EBADF)) {
|
|
t.Errorf("Close: error = %v", err)
|
|
return
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkExport(b *testing.B) {
|
|
buf := make([]byte, 8)
|
|
for i := 0; i < b.N; i++ {
|
|
e := New(
|
|
Preset(PresetExt|PresetDenyNS|PresetDenyTTY|PresetDenyDevel|PresetLinux32,
|
|
AllowMultiarch|AllowCAN|AllowBluetooth),
|
|
AllowMultiarch|AllowCAN|AllowBluetooth)
|
|
if _, err := io.CopyBuffer(io.Discard, e, buf); err != nil {
|
|
b.Fatalf("cannot export: %v", err)
|
|
}
|
|
if err := e.Close(); err != nil {
|
|
b.Fatalf("cannot close exporter: %v", err)
|
|
}
|
|
}
|
|
}
|