diff --git a/pkg/bpf/interpreter.go b/pkg/bpf/interpreter.go index de06bc694..cde771154 100644 --- a/pkg/bpf/interpreter.go +++ b/pkg/bpf/interpreter.go @@ -97,8 +97,8 @@ func (p Program) Length() int { return len(p.instructions) } -// Compile performs validation on a sequence of BPF instructions before -// wrapping them in a Program. +// Compile performs validation and optimization on a sequence of BPF +// instructions before wrapping them in a Program. func Compile(insns []Instruction) (Program, error) { if len(insns) == 0 || len(insns) > MaxInstructions { return Program{}, Error{InvalidInstructionCount, len(insns)} @@ -214,7 +214,7 @@ func Compile(insns []Instruction) (Program, error) { } } - return Program{insns}, nil + return Program{Optimize(insns)}, nil } // Input represents a source of input data for a BPF program. (BPF diff --git a/pkg/bpf/interpreter_test.go b/pkg/bpf/interpreter_test.go index 8052d2f46..cc5086e8f 100644 --- a/pkg/bpf/interpreter_test.go +++ b/pkg/bpf/interpreter_test.go @@ -705,6 +705,19 @@ func TestValidInstructions(t *testing.T) { }, expectedRet: 2, }, + { + desc: "Optimizable program", + insns: []Instruction{ + Stmt(Ld|Imm|W, 42), // A = 42 + Jump(Jmp|Jeq|K, 42, 0, 1), // if (A == 42) jmp 0 else 1 + Jump(Jmp|Ja, 1, 0, 0), // jmp 1 + Jump(Jmp|Ja, 2, 0, 0), // jmp 2 + Stmt(Ld|Imm|W, 37), // A = 37 + Stmt(Ret|K, 0), // return 0 + Stmt(Ret|K, 1), // return 1 + }, + expectedRet: 0, + }, } { p, err := Compile(test.insns) if err != nil { diff --git a/pkg/seccomp/seccomp.go b/pkg/seccomp/seccomp.go index 9f476f3ab..c0879e6f9 100644 --- a/pkg/seccomp/seccomp.go +++ b/pkg/seccomp/seccomp.go @@ -152,7 +152,15 @@ func BuildProgram(rules []RuleSet, defaultAction, badArchAction linux.BPFAction) } program.AddStmt(bpf.Ret|bpf.K, uint32(defaultAction)) - return program.Instructions() + insns, err := program.Instructions() + if err != nil { + return insns, err + } + beforeOpt := len(insns) + insns = bpf.Optimize(insns) + afterOpt := len(insns) + log.Debugf("Seccomp program optimized from %d to %d instructions", beforeOpt, afterOpt) + return insns, nil } // buildIndex builds a BST to quickly search through all syscalls.