mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
bpf: Do not use interfaces to define byte ordering in BPF evaluation.
This speeds up BPF evaluation by avoiding interface call overhead.
```
│ initial │ hey_look_no_interfaces │ even_fewer_interfaces │
│ sec/op │ sec/op vs base │ sec/op vs base │
Interpreter 26.31n ± 0% 21.87n ± 0% -16.88% (p=0.000 n=21+20) 14.26n ± 0% -45.80% (p=0.000 n=21+20)
```
PiperOrigin-RevId: 576591719
This commit is contained in:
committed by
gVisor bot
parent
ecbf37d037
commit
663e69bde4
+56
-24
@@ -22,47 +22,79 @@ import (
|
||||
// documentation sometimes refers to the input data as the "packet" due to its
|
||||
// origins as a packet processing DSL.)
|
||||
// Unaligned loads are supported.
|
||||
type Input struct {
|
||||
// Data is the data accessed through the Input interface.
|
||||
Data []byte
|
||||
type Input []byte
|
||||
|
||||
// Order is the byte order the data is accessed with.
|
||||
Order binary.ByteOrder
|
||||
// These type definitions must have different GC shapes to ensure that
|
||||
// the Go compiler generates distinct code paths for them.
|
||||
// These do not have anything to do with the bit sizes of the loads
|
||||
// later on; all that matters is that these types have distinct sizes
|
||||
// from one another.
|
||||
type (
|
||||
// BigEndian uses big-endian byte ordering.
|
||||
BigEndian uint8
|
||||
|
||||
// LittleEndian uses little-endian byte ordering.
|
||||
LittleEndian uint16
|
||||
|
||||
// NativeEndian uses native byte ordering.
|
||||
NativeEndian uint32
|
||||
)
|
||||
|
||||
// Endianness represents a byte order.
|
||||
type Endianness interface {
|
||||
BigEndian | LittleEndian | NativeEndian
|
||||
}
|
||||
|
||||
// Load32 implements Input.Load32.
|
||||
// load32 loads a 32-bit value.
|
||||
//
|
||||
//go:nosplit
|
||||
func (i *Input) Load32(off uint32) (uint32, bool) {
|
||||
if uint64(off)+4 > uint64(len(i.Data)) {
|
||||
func load32[endian Endianness](in Input, off uint32) (uint32, bool) {
|
||||
if uint64(off)+4 > uint64(len(in)) {
|
||||
return 0, false
|
||||
}
|
||||
return i.Order.Uint32(i.Data[int(off):]), true
|
||||
// Casting to any is needed here to avoid a compilation error:
|
||||
// https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#why-not-permit-type-assertions-on-values-whose-type-is-a-type-parameter
|
||||
var e endian
|
||||
switch any(e).(type) {
|
||||
case BigEndian:
|
||||
return binary.BigEndian.Uint32(in[int(off):]), true
|
||||
case LittleEndian:
|
||||
return binary.LittleEndian.Uint32(in[int(off):]), true
|
||||
case NativeEndian:
|
||||
return binary.NativeEndian.Uint32(in[int(off):]), true
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// Load16 implements Input.Load16.
|
||||
// load16 loads a 16-bit value.
|
||||
//
|
||||
//go:nosplit
|
||||
func (i *Input) Load16(off uint32) (uint16, bool) {
|
||||
if uint64(off)+2 > uint64(len(i.Data)) {
|
||||
func load16[endian Endianness](in Input, off uint32) (uint16, bool) {
|
||||
if uint64(off)+2 > uint64(len(in)) {
|
||||
return 0, false
|
||||
}
|
||||
return i.Order.Uint16(i.Data[int(off):]), true
|
||||
// Casting to any is needed here to avoid a compilation error:
|
||||
// https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#why-not-permit-type-assertions-on-values-whose-type-is-a-type-parameter
|
||||
var e endian
|
||||
switch any(e).(type) {
|
||||
case BigEndian:
|
||||
return binary.BigEndian.Uint16(in[int(off):]), true
|
||||
case LittleEndian:
|
||||
return binary.LittleEndian.Uint16(in[int(off):]), true
|
||||
case NativeEndian:
|
||||
return binary.NativeEndian.Uint16(in[int(off):]), true
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// Load8 implements Input.Load8.
|
||||
// load8 loads a single byte.
|
||||
//
|
||||
//go:nosplit
|
||||
func (i *Input) Load8(off uint32) (uint8, bool) {
|
||||
if uint64(off)+1 > uint64(len(i.Data)) {
|
||||
func load8(in Input, off uint32) (uint8, bool) {
|
||||
if uint64(off)+1 > uint64(len(in)) {
|
||||
return 0, false
|
||||
}
|
||||
return i.Data[int(off)], true
|
||||
}
|
||||
|
||||
// Length implements Input.Length.
|
||||
//
|
||||
//go:nosplit
|
||||
func (i *Input) Length() uint32 {
|
||||
return uint32(len(i.Data))
|
||||
return in[int(off)], true
|
||||
}
|
||||
|
||||
+21
-21
@@ -238,7 +238,7 @@ func conditionalJumpOffset(insn Instruction, cond bool) int {
|
||||
|
||||
// Exec executes a BPF program over the given input and returns its return
|
||||
// value.
|
||||
func Exec(p Program, in Input) (uint32, error) {
|
||||
func Exec[endian Endianness](p Program, in Input) (uint32, error) {
|
||||
var m machine
|
||||
var pc int
|
||||
for ; pc < len(p.instructions); pc++ {
|
||||
@@ -247,37 +247,37 @@ func Exec(p Program, in Input) (uint32, error) {
|
||||
case Ld | Imm | W:
|
||||
m.A = i.K
|
||||
case Ld | Abs | W:
|
||||
val, ok := in.Load32(i.K)
|
||||
val, ok := load32[endian](in, i.K)
|
||||
if !ok {
|
||||
return 0, Error{InvalidLoad, pc}
|
||||
}
|
||||
m.A = val
|
||||
case Ld | Abs | H:
|
||||
val, ok := in.Load16(i.K)
|
||||
val, ok := load16[endian](in, i.K)
|
||||
if !ok {
|
||||
return 0, Error{InvalidLoad, pc}
|
||||
}
|
||||
m.A = uint32(val)
|
||||
case Ld | Abs | B:
|
||||
val, ok := in.Load8(i.K)
|
||||
val, ok := load8(in, i.K)
|
||||
if !ok {
|
||||
return 0, Error{InvalidLoad, pc}
|
||||
}
|
||||
m.A = uint32(val)
|
||||
case Ld | Ind | W:
|
||||
val, ok := in.Load32(m.X + i.K)
|
||||
val, ok := load32[endian](in, m.X+i.K)
|
||||
if !ok {
|
||||
return 0, Error{InvalidLoad, pc}
|
||||
}
|
||||
m.A = val
|
||||
case Ld | Ind | H:
|
||||
val, ok := in.Load16(m.X + i.K)
|
||||
val, ok := load16[endian](in, m.X+i.K)
|
||||
if !ok {
|
||||
return 0, Error{InvalidLoad, pc}
|
||||
}
|
||||
m.A = uint32(val)
|
||||
case Ld | Ind | B:
|
||||
val, ok := in.Load8(m.X + i.K)
|
||||
val, ok := load8(in, m.X+i.K)
|
||||
if !ok {
|
||||
return 0, Error{InvalidLoad, pc}
|
||||
}
|
||||
@@ -285,15 +285,15 @@ func Exec(p Program, in Input) (uint32, error) {
|
||||
case Ld | Mem | W:
|
||||
m.A = m.M[int(i.K)]
|
||||
case Ld | Len | W:
|
||||
m.A = in.Length()
|
||||
m.A = uint32(len(in))
|
||||
case Ldx | Imm | W:
|
||||
m.X = i.K
|
||||
case Ldx | Mem | W:
|
||||
m.X = m.M[int(i.K)]
|
||||
case Ldx | Len | W:
|
||||
m.X = in.Length()
|
||||
m.X = uint32(len(in))
|
||||
case Ldx | Msh | B:
|
||||
val, ok := in.Load8(i.K)
|
||||
val, ok := load8(in, i.K)
|
||||
if !ok {
|
||||
return 0, Error{InvalidLoad, pc}
|
||||
}
|
||||
@@ -497,10 +497,10 @@ func (e *ExecutionMetrics) markInputRead(offset uint32, bytesRead int) {
|
||||
// InstrumentedExec executes a BPF program over the given input while
|
||||
// instrumenting it: recording memory accesses and lines executed.
|
||||
// This is slower than Exec, but should return equivalent results.
|
||||
func InstrumentedExec(p Program, in Input) (ExecutionMetrics, error) {
|
||||
func InstrumentedExec[endian Endianness](p Program, in Input) (ExecutionMetrics, error) {
|
||||
ret := ExecutionMetrics{
|
||||
Coverage: make([]bool, len(p.instructions)),
|
||||
InputAccessed: make([]bool, in.Length()),
|
||||
InputAccessed: make([]bool, len(in)),
|
||||
}
|
||||
var m machine
|
||||
var pc int
|
||||
@@ -511,42 +511,42 @@ func InstrumentedExec(p Program, in Input) (ExecutionMetrics, error) {
|
||||
case Ld | Imm | W:
|
||||
m.A = i.K
|
||||
case Ld | Abs | W:
|
||||
val, ok := in.Load32(i.K)
|
||||
val, ok := load32[endian](in, i.K)
|
||||
if !ok {
|
||||
return ret, Error{InvalidLoad, pc}
|
||||
}
|
||||
ret.markInputRead(i.K, 4)
|
||||
m.A = val
|
||||
case Ld | Abs | H:
|
||||
val, ok := in.Load16(i.K)
|
||||
val, ok := load16[endian](in, i.K)
|
||||
if !ok {
|
||||
return ret, Error{InvalidLoad, pc}
|
||||
}
|
||||
ret.markInputRead(i.K, 2)
|
||||
m.A = uint32(val)
|
||||
case Ld | Abs | B:
|
||||
val, ok := in.Load8(i.K)
|
||||
val, ok := load8(in, i.K)
|
||||
if !ok {
|
||||
return ret, Error{InvalidLoad, pc}
|
||||
}
|
||||
ret.markInputRead(i.K, 1)
|
||||
m.A = uint32(val)
|
||||
case Ld | Ind | W:
|
||||
val, ok := in.Load32(m.X + i.K)
|
||||
val, ok := load32[endian](in, m.X+i.K)
|
||||
if !ok {
|
||||
return ret, Error{InvalidLoad, pc}
|
||||
}
|
||||
ret.markInputRead(m.X+i.K, 4)
|
||||
m.A = val
|
||||
case Ld | Ind | H:
|
||||
val, ok := in.Load16(m.X + i.K)
|
||||
val, ok := load16[endian](in, m.X+i.K)
|
||||
if !ok {
|
||||
return ret, Error{InvalidLoad, pc}
|
||||
}
|
||||
ret.markInputRead(m.X+i.K, 2)
|
||||
m.A = uint32(val)
|
||||
case Ld | Ind | B:
|
||||
val, ok := in.Load8(m.X + i.K)
|
||||
val, ok := load8(in, m.X+i.K)
|
||||
if !ok {
|
||||
return ret, Error{InvalidLoad, pc}
|
||||
}
|
||||
@@ -555,15 +555,15 @@ func InstrumentedExec(p Program, in Input) (ExecutionMetrics, error) {
|
||||
case Ld | Mem | W:
|
||||
m.A = m.M[int(i.K)]
|
||||
case Ld | Len | W:
|
||||
m.A = in.Length()
|
||||
m.A = uint32(len(in))
|
||||
case Ldx | Imm | W:
|
||||
m.X = i.K
|
||||
case Ldx | Mem | W:
|
||||
m.X = m.M[int(i.K)]
|
||||
case Ldx | Len | W:
|
||||
m.X = in.Length()
|
||||
m.X = uint32(len(in))
|
||||
case Ldx | Msh | B:
|
||||
val, ok := in.Load8(i.K)
|
||||
val, ok := load8(in, i.K)
|
||||
if !ok {
|
||||
return ret, Error{InvalidLoad, pc}
|
||||
}
|
||||
|
||||
+16
-18
@@ -15,7 +15,6 @@
|
||||
package bpf
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -153,12 +152,12 @@ func TestExecErrors(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected compilation error: %v", err)
|
||||
}
|
||||
inp := Input{nil, binary.BigEndian}
|
||||
execution, err := InstrumentedExec(p, inp)
|
||||
inp := Input{}
|
||||
execution, err := InstrumentedExec[NativeEndian](p, inp)
|
||||
if err != test.expectedErr {
|
||||
t.Fatalf("expected execution error %q, got (%v, %v)", test.expectedErr, execution, err)
|
||||
}
|
||||
ret, err := Exec(p, inp)
|
||||
ret, err := Exec[NativeEndian](p, inp)
|
||||
if err != test.expectedErr {
|
||||
t.Fatalf("expected execution error %q, got (%d, %v)", test.expectedErr, ret, err)
|
||||
}
|
||||
@@ -166,7 +165,7 @@ func TestExecErrors(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected compilation error: %v", err)
|
||||
}
|
||||
if _, err := InstrumentedExec(optimizedProgram, inp); err != test.expectedErr {
|
||||
if _, err := InstrumentedExec[NativeEndian](optimizedProgram, inp); err != test.expectedErr {
|
||||
t.Fatalf("expected execution error from optimized program %q, got (%v, %v)", test.expectedErr, execution, err)
|
||||
}
|
||||
})
|
||||
@@ -200,7 +199,7 @@ func TestValidInstructions(t *testing.T) {
|
||||
insns []Instruction
|
||||
|
||||
// input is the input data. Note that input will be read as big-endian.
|
||||
input []byte
|
||||
input Input
|
||||
|
||||
// expected is the expected result of executing the BPF program.
|
||||
// It takes in the instructions and input that the test will run.
|
||||
@@ -251,7 +250,7 @@ func TestValidInstructions(t *testing.T) {
|
||||
expected: want(ExecutionMetrics{
|
||||
Coverage: []bool{true, true},
|
||||
InputAccessed: []bool{false, true, true, true, true, false},
|
||||
ReturnValue: 0x11223344,
|
||||
ReturnValue: hostarch.ByteOrder.Uint32([]byte{0x11, 0x22, 0x33, 0x44}),
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -264,7 +263,7 @@ func TestValidInstructions(t *testing.T) {
|
||||
expected: want(ExecutionMetrics{
|
||||
Coverage: []bool{true, true},
|
||||
InputAccessed: []bool{false, true, true, false},
|
||||
ReturnValue: 0x1122,
|
||||
ReturnValue: uint32(hostarch.ByteOrder.Uint16([]byte{0x11, 0x22})),
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -291,7 +290,7 @@ func TestValidInstructions(t *testing.T) {
|
||||
expected: want(ExecutionMetrics{
|
||||
Coverage: []bool{true, true, true},
|
||||
InputAccessed: []bool{false, false, true, true, true, true, false},
|
||||
ReturnValue: 0x22334455,
|
||||
ReturnValue: hostarch.ByteOrder.Uint32([]byte{0x22, 0x33, 0x44, 0x55}),
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -305,7 +304,7 @@ func TestValidInstructions(t *testing.T) {
|
||||
expected: want(ExecutionMetrics{
|
||||
Coverage: []bool{true, true, true},
|
||||
InputAccessed: []bool{false, false, true, true, false},
|
||||
ReturnValue: 0x2233,
|
||||
ReturnValue: uint32(hostarch.ByteOrder.Uint16([]byte{0x22, 0x33})),
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -862,15 +861,14 @@ func TestValidInstructions(t *testing.T) {
|
||||
t.Fatalf("unexpected compilation error: %v", err)
|
||||
}
|
||||
want := test.expected(test.insns, test.input)
|
||||
inp := Input{test.input, binary.BigEndian}
|
||||
execution, err := InstrumentedExec(p, inp)
|
||||
execution, err := InstrumentedExec[NativeEndian](p, test.input)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected execution error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(execution, want) {
|
||||
t.Fatalf("expected %s, got %s", want.String(), execution.String())
|
||||
}
|
||||
retFast, err := Exec(p, inp)
|
||||
retFast, err := Exec[NativeEndian](p, test.input)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected execution error during fast execution: %v", err)
|
||||
}
|
||||
@@ -881,7 +879,7 @@ func TestValidInstructions(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected compilation error: %v", err)
|
||||
}
|
||||
retOptimized, err := InstrumentedExec(optimizedProgram, inp)
|
||||
retOptimized, err := InstrumentedExec[NativeEndian](optimizedProgram, test.input)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected execution error: %v", err)
|
||||
}
|
||||
@@ -1031,7 +1029,7 @@ func TestSimpleFilter(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
execution, err := InstrumentedExec(p, dataAsInput(&test.data))
|
||||
execution, err := InstrumentedExec[NativeEndian](p, dataAsInput(&test.data))
|
||||
if err != nil {
|
||||
t.Fatalf("expected return value of %d, got execution error: %v", test.expected.ReturnValue, err)
|
||||
}
|
||||
@@ -1044,7 +1042,7 @@ func TestSimpleFilter(t *testing.T) {
|
||||
|
||||
// asInput converts a seccompData to a bpf.Input.
|
||||
func dataAsInput(data *linux.SeccompData) Input {
|
||||
return Input{marshal.Marshal(data), hostarch.ByteOrder}
|
||||
return marshal.Marshal(data)
|
||||
}
|
||||
|
||||
// BenchmarkInterpreter benchmarks the execution of the sample filter
|
||||
@@ -1057,7 +1055,7 @@ func BenchmarkInterpreter(b *testing.B) {
|
||||
data := dataAsInput(&linux.SeccompData{Nr: 231 /* __NR_exit_group */, Arch: 0xc000003e})
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := Exec(p, data); err != nil {
|
||||
if _, err := Exec[NativeEndian](p, data); err != nil {
|
||||
b.Fatalf("Unexpected execution error: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -1071,7 +1069,7 @@ func BenchmarkInstrumentedInterpreter(b *testing.B) {
|
||||
data := dataAsInput(&linux.SeccompData{Nr: 231 /* __NR_exit_group */, Arch: 0xc000003e})
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := InstrumentedExec(p, data); err != nil {
|
||||
if _, err := InstrumentedExec[NativeEndian](p, data); err != nil {
|
||||
b.Fatalf("Unexpected execution error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/bpf",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/log",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/bpf"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
)
|
||||
|
||||
@@ -501,8 +500,5 @@ func DataAsBPFInput(d *linux.SeccompData, buf []byte) bpf.Input {
|
||||
panic(fmt.Sprintf("buffer must be at least %d bytes long", d.SizeBytes()))
|
||||
}
|
||||
d.MarshalUnsafe(buf)
|
||||
return bpf.Input{
|
||||
Data: buf,
|
||||
Order: hostarch.ByteOrder,
|
||||
}
|
||||
return buf[:d.SizeBytes()]
|
||||
}
|
||||
|
||||
@@ -877,9 +877,9 @@ func TestBasic(t *testing.T) {
|
||||
t.Fatalf("bpf.Compile got error: %v", err)
|
||||
}
|
||||
for _, spec := range test.specs {
|
||||
got, err := bpf.Exec(p, DataAsBPFInput(&spec.data, buf))
|
||||
got, err := bpf.Exec[bpf.NativeEndian](p, DataAsBPFInput(&spec.data, buf))
|
||||
if err != nil {
|
||||
t.Fatalf("%s: bpf.Exec() got error: %v", spec.desc, err)
|
||||
t.Fatalf("%s: bpf.Exec got error: %v", spec.desc, err)
|
||||
}
|
||||
if got != uint32(spec.want) {
|
||||
// Include a decoded version of the program in output for debugging purposes.
|
||||
@@ -920,9 +920,9 @@ func TestRandom(t *testing.T) {
|
||||
buf := make([]byte, (&linux.SeccompData{}).SizeBytes())
|
||||
for i := uint32(0); i < 200; i++ {
|
||||
data := linux.SeccompData{Nr: int32(i), Arch: LINUX_AUDIT_ARCH}
|
||||
got, err := bpf.Exec(p, DataAsBPFInput(&data, buf))
|
||||
got, err := bpf.Exec[bpf.NativeEndian](p, DataAsBPFInput(&data, buf))
|
||||
if err != nil {
|
||||
t.Errorf("bpf.Exec() got error: %v, for syscall %d", err, i)
|
||||
t.Errorf("bpf.Exec got error: %v, for syscall %d", err, i)
|
||||
continue
|
||||
}
|
||||
want := linux.SECCOMP_RET_TRAP
|
||||
@@ -930,7 +930,7 @@ func TestRandom(t *testing.T) {
|
||||
want = linux.SECCOMP_RET_ALLOW
|
||||
}
|
||||
if got != uint32(want) {
|
||||
t.Errorf("bpf.Exec() = %d, want: %d, for syscall %d", got, want, i)
|
||||
t.Errorf("bpf.Exec = %d, want: %d, for syscall %d", got, want, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,7 @@ const maxSyscallFilterInstructions = 1 << 15
|
||||
func dataAsBPFInput(t *Task, d *linux.SeccompData) bpf.Input {
|
||||
buf := t.CopyScratchBuffer(d.SizeBytes())
|
||||
d.MarshalUnsafe(buf)
|
||||
return bpf.Input{
|
||||
Data: buf,
|
||||
// Go-marshal always uses the native byte order.
|
||||
Order: hostarch.ByteOrder,
|
||||
}
|
||||
return buf[:d.SizeBytes()]
|
||||
}
|
||||
|
||||
func seccompSiginfo(t *Task, errno, sysno int32, ip hostarch.Addr) *linux.SignalInfo {
|
||||
@@ -127,7 +123,7 @@ func (t *Task) evaluateSyscallFilters(sysno int32, args arch.SyscallArguments, i
|
||||
// "Every filter successfully installed will be evaluated (in reverse
|
||||
// order) for each system call the task makes." - kernel/seccomp.c
|
||||
for i := len(f.([]bpf.Program)) - 1; i >= 0; i-- {
|
||||
thisRet, err := bpf.Exec(f.([]bpf.Program)[i], input)
|
||||
thisRet, err := bpf.Exec[bpf.NativeEndian](f.([]bpf.Program)[i], input)
|
||||
if err != nil {
|
||||
t.Debugf("seccomp-bpf filter %d returned error: %v", i, err)
|
||||
thisRet = uint32(linux.SECCOMP_RET_KILL_THREAD)
|
||||
|
||||
@@ -390,7 +390,7 @@ func TestRunscSeccomp(t *testing.T) {
|
||||
// checkProgram runs the given program over the given input and checks the
|
||||
// result against the expected output.
|
||||
func checkProgram(p bpf.Program, in bpf.Input, expected uint32) error {
|
||||
result, err := bpf.Exec(p, in)
|
||||
result, err := bpf.Exec[bpf.NativeEndian](p, in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ func runRequest(runReq secbenchdef.BenchRunRequest) (secbenchdef.BenchRunRespons
|
||||
}
|
||||
|
||||
func evalSyscall(program bpf.Program, arch uint32, sc secbenchdef.Syscall, buf []byte) (uint32, error) {
|
||||
return bpf.Exec(program, seccomp.DataAsBPFInput(&linux.SeccompData{
|
||||
return bpf.Exec[bpf.NativeEndian](program, seccomp.DataAsBPFInput(&linux.SeccompData{
|
||||
Nr: int32(sc.Sysno),
|
||||
Arch: arch,
|
||||
Args: [6]uint64{
|
||||
|
||||
Reference in New Issue
Block a user