1
2
3
4
5 package bpf_test
6
7 import (
8 "net"
9 "testing"
10
11 "golang.org/x/net/bpf"
12 "golang.org/x/net/ipv4"
13 )
14
15 func TestVMLoadAbsoluteOffsetOutOfBounds(t *testing.T) {
16 pkt := []byte{
17 0xff, 0xff, 0xff, 0xff,
18 0xff, 0xff, 0xff, 0xff,
19 0, 1, 2, 3,
20 }
21
22 vm, done, err := testVM(t, []bpf.Instruction{
23 bpf.LoadAbsolute{
24 Off: uint32(len(pkt)),
25 Size: 1,
26 },
27
28 bpf.RetConstant{Val: 1},
29 })
30 if err != nil {
31 t.Fatalf("failed to load BPF program: %v", err)
32 }
33 defer done()
34
35 out, err := vm.Run(pkt)
36 if err != nil {
37 t.Fatalf("unexpected error while running program: %v", err)
38 }
39 if want, got := 0, out; want != got {
40 t.Fatalf("unexpected result:\n- want: %d\n- got: %d",
41 want, got)
42 }
43 }
44
45 func TestVMLoadAbsoluteOffsetPlusSizeOutOfBounds(t *testing.T) {
46 pkt := []byte{
47 0xff, 0xff, 0xff, 0xff,
48 0xff, 0xff, 0xff, 0xff,
49 0,
50 }
51
52 vm, done, err := testVM(t, []bpf.Instruction{
53 bpf.LoadAbsolute{
54 Off: uint32(len(pkt) - 1),
55 Size: 2,
56 },
57
58 bpf.RetConstant{Val: 1},
59 })
60 if err != nil {
61 t.Fatalf("failed to load BPF program: %v", err)
62 }
63 defer done()
64
65 out, err := vm.Run(pkt)
66 if err != nil {
67 t.Fatalf("unexpected error while running program: %v", err)
68 }
69 if want, got := 0, out; want != got {
70 t.Fatalf("unexpected result:\n- want: %d\n- got: %d",
71 want, got)
72 }
73 }
74
75 func TestVMLoadAbsoluteBadInstructionSize(t *testing.T) {
76 _, _, err := testVM(t, []bpf.Instruction{
77 bpf.LoadAbsolute{
78 Size: 5,
79 },
80 bpf.RetA{},
81 })
82 if errStr(err) != "assembling instruction 1: invalid load byte length 0" {
83 t.Fatalf("unexpected error: %v", err)
84 }
85 }
86
87 func TestVMLoadConstantOK(t *testing.T) {
88 vm, done, err := testVM(t, []bpf.Instruction{
89 bpf.LoadConstant{
90 Dst: bpf.RegX,
91 Val: 9,
92 },
93 bpf.TXA{},
94 bpf.RetA{},
95 })
96 if err != nil {
97 t.Fatalf("failed to load BPF program: %v", err)
98 }
99 defer done()
100
101 out, err := vm.Run([]byte{
102 0xff, 0xff, 0xff, 0xff,
103 0xff, 0xff, 0xff, 0xff,
104 0,
105 })
106 if err != nil {
107 t.Fatalf("unexpected error while running program: %v", err)
108 }
109 if want, got := 1, out; want != got {
110 t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
111 want, got)
112 }
113 }
114
115 func TestVMLoadIndirectOutOfBounds(t *testing.T) {
116 pkt := []byte{
117 0xff, 0xff, 0xff, 0xff,
118 0xff, 0xff, 0xff, 0xff,
119 0,
120 }
121
122 vm, done, err := testVM(t, []bpf.Instruction{
123 bpf.LoadIndirect{
124 Off: uint32(len(pkt)),
125 Size: 1,
126 },
127
128 bpf.RetConstant{Val: 1},
129 })
130 if err != nil {
131 t.Fatalf("failed to load BPF program: %v", err)
132 }
133 defer done()
134
135 out, err := vm.Run(pkt)
136 if err != nil {
137 t.Fatalf("unexpected error while running program: %v", err)
138 }
139 if want, got := 0, out; want != got {
140 t.Fatalf("unexpected result:\n- want: %d\n- got: %d",
141 want, got)
142 }
143 }
144
145 func TestVMLoadMemShiftOutOfBounds(t *testing.T) {
146 pkt := []byte{
147 0xff, 0xff, 0xff, 0xff,
148 0xff, 0xff, 0xff, 0xff,
149 0,
150 }
151
152 vm, done, err := testVM(t, []bpf.Instruction{
153 bpf.LoadMemShift{
154 Off: uint32(len(pkt)),
155 },
156
157 bpf.RetConstant{Val: 1},
158 })
159 if err != nil {
160 t.Fatalf("failed to load BPF program: %v", err)
161 }
162 defer done()
163
164 out, err := vm.Run(pkt)
165 if err != nil {
166 t.Fatalf("unexpected error while running program: %v", err)
167 }
168 if want, got := 0, out; want != got {
169 t.Fatalf("unexpected result:\n- want: %d\n- got: %d",
170 want, got)
171 }
172 }
173
174 const (
175 dhcp4Port = 53
176 )
177
178 func TestVMLoadMemShiftLoadIndirectNoResult(t *testing.T) {
179 vm, in, done := testDHCPv4(t)
180 defer done()
181
182
183 in = append(in, []byte{
184 0, 0,
185 0, dhcp4Port + 1,
186 0, 0,
187 0, 0,
188 }...)
189
190 out, err := vm.Run(in)
191 if err != nil {
192 t.Fatalf("unexpected error while running program: %v", err)
193 }
194 if want, got := 0, out; want != got {
195 t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
196 want, got)
197 }
198 }
199
200 func TestVMLoadMemShiftLoadIndirectOK(t *testing.T) {
201 vm, in, done := testDHCPv4(t)
202 defer done()
203
204
205 in = append(in, []byte{
206 0, 0,
207 0, dhcp4Port,
208 0, 0,
209 0, 0,
210 }...)
211
212 out, err := vm.Run(in)
213 if err != nil {
214 t.Fatalf("unexpected error while running program: %v", err)
215 }
216 if want, got := len(in)-8, out; want != got {
217 t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
218 want, got)
219 }
220 }
221
222 func testDHCPv4(t *testing.T) (virtualMachine, []byte, func()) {
223
224
225 vm, done, err := testVM(t, []bpf.Instruction{
226
227 bpf.LoadMemShift{Off: 8},
228
229 bpf.LoadIndirect{Off: 8 + 2, Size: 2},
230
231 bpf.JumpIf{Cond: bpf.JumpEqual, Val: dhcp4Port, SkipFalse: 1},
232
233 bpf.RetConstant{Val: 1500},
234
235 bpf.RetConstant{Val: 0},
236 })
237 if err != nil {
238 t.Fatalf("failed to load BPF program: %v", err)
239 }
240
241
242 h := &ipv4.Header{
243 Len: ipv4.HeaderLen,
244 Src: net.IPv4(192, 168, 1, 1),
245 Dst: net.IPv4(192, 168, 1, 2),
246 }
247 hb, err := h.Marshal()
248 if err != nil {
249 t.Fatalf("failed to marshal IPv4 header: %v", err)
250 }
251
252 hb = append([]byte{
253 0xff, 0xff, 0xff, 0xff,
254 0xff, 0xff, 0xff, 0xff,
255 }, hb...)
256
257 return vm, hb, done
258 }
259
View as plain text