1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package bpf

import "testing"

// TestAssembleSimpleJEQ checks basic label resolution without trampolines.
func TestAssembleSimpleJEQ(t *testing.T) {
	p := NewProgram()
	p.Stmt(OpLdAbsW, OffNr)
	p.Jump(OpJeqK, 42, "hit", "")
	p.Ret(0xdead)
	p.Label("hit")
	p.Ret(0xbeef)

	prog, err := p.Assemble()
	if err != nil {
		t.Fatal(err)
	}
	if got, _ := Run(prog, SeccompData{Nr: 42}); got != 0xbeef {
		t.Errorf("nr=42: got 0x%x want 0xbeef", got)
	}
	if got, _ := Run(prog, SeccompData{Nr: 1}); got != 0xdead {
		t.Errorf("nr=1: got 0x%x want 0xdead", got)
	}
}

// TestAssembleLongJumpViaJA verifies that a long jump expressed with BPF_JA
// (32-bit offset) works regardless of distance, with no trampolining.
func TestAssembleLongJumpViaJA(t *testing.T) {
	p := NewProgram()
	p.Stmt(OpLdAbsW, OffNr)
	// JEQ jumps to a *nearby* JA, which long-jumps over the filler.
	p.Jump(OpJeqK, 7, "tramp", "")
	p.Ret(0x1111) // not-7 path
	p.Label("tramp")
	p.Ja("far")
	for i := 0; i < 300; i++ {
		p.Stmt(OpLdImmW, uint32(i))
	}
	p.Label("far")
	p.Ret(0x2222)

	prog, err := p.Assemble()
	if err != nil {
		t.Fatalf("Assemble: %v", err)
	}
	if got, _ := Run(prog, SeccompData{Nr: 7}); got != 0x2222 {
		t.Errorf("nr=7: got 0x%x want 0x2222 (JA path)", got)
	}
	if got, _ := Run(prog, SeccompData{Nr: 8}); got != 0x1111 {
		t.Errorf("nr=8: got 0x%x want 0x1111 (fallthrough path)", got)
	}
}

// TestAssembleConditionalOverflowErrors verifies that a conditional jump whose
// target is more than 255 instructions away is reported as an error (the static
// guarantee that replaced auto-trampolining), rather than silently truncated.
func TestAssembleConditionalOverflowErrors(t *testing.T) {
	p := NewProgram()
	p.Stmt(OpLdAbsW, OffNr)
	p.Jump(OpJeqK, 7, "far", "")
	for i := 0; i < 300; i++ {
		p.Stmt(OpLdImmW, uint32(i))
	}
	p.Label("far")
	p.Ret(0x2222)

	if _, err := p.Assemble(); err == nil {
		t.Fatal("expected an error for a >255 conditional jump, got nil")
	}
}