blob: 7b56b59fad8ebb6e29ff0885efb20d0b847ffb89 [file] [log] [blame]
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -07001/*
2 * Testsuite for eBPF verifier
3 *
4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 */
10#include <stdio.h>
11#include <unistd.h>
12#include <linux/bpf.h>
13#include <errno.h>
14#include <linux/unistd.h>
15#include <string.h>
16#include <linux/filter.h>
17#include "libbpf.h"
18
19#define MAX_INSNS 512
20#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
21
22struct bpf_test {
23 const char *descr;
24 struct bpf_insn insns[MAX_INSNS];
25 int fixup[32];
26 const char *errstr;
27 enum {
28 ACCEPT,
29 REJECT
30 } result;
31};
32
33static struct bpf_test tests[] = {
34 {
35 "add+sub+mul",
36 .insns = {
37 BPF_MOV64_IMM(BPF_REG_1, 1),
38 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 2),
39 BPF_MOV64_IMM(BPF_REG_2, 3),
40 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_2),
41 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1),
42 BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 3),
43 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
44 BPF_EXIT_INSN(),
45 },
46 .result = ACCEPT,
47 },
48 {
49 "unreachable",
50 .insns = {
51 BPF_EXIT_INSN(),
52 BPF_EXIT_INSN(),
53 },
54 .errstr = "unreachable",
55 .result = REJECT,
56 },
57 {
58 "unreachable2",
59 .insns = {
60 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
61 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
62 BPF_EXIT_INSN(),
63 },
64 .errstr = "unreachable",
65 .result = REJECT,
66 },
67 {
68 "out of range jump",
69 .insns = {
70 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
71 BPF_EXIT_INSN(),
72 },
73 .errstr = "jump out of range",
74 .result = REJECT,
75 },
76 {
77 "out of range jump2",
78 .insns = {
79 BPF_JMP_IMM(BPF_JA, 0, 0, -2),
80 BPF_EXIT_INSN(),
81 },
82 .errstr = "jump out of range",
83 .result = REJECT,
84 },
85 {
86 "test1 ld_imm64",
87 .insns = {
88 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
89 BPF_LD_IMM64(BPF_REG_0, 0),
90 BPF_LD_IMM64(BPF_REG_0, 0),
91 BPF_LD_IMM64(BPF_REG_0, 1),
92 BPF_LD_IMM64(BPF_REG_0, 1),
93 BPF_MOV64_IMM(BPF_REG_0, 2),
94 BPF_EXIT_INSN(),
95 },
96 .errstr = "invalid BPF_LD_IMM insn",
97 .result = REJECT,
98 },
99 {
100 "test2 ld_imm64",
101 .insns = {
102 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
103 BPF_LD_IMM64(BPF_REG_0, 0),
104 BPF_LD_IMM64(BPF_REG_0, 0),
105 BPF_LD_IMM64(BPF_REG_0, 1),
106 BPF_LD_IMM64(BPF_REG_0, 1),
107 BPF_EXIT_INSN(),
108 },
109 .errstr = "invalid BPF_LD_IMM insn",
110 .result = REJECT,
111 },
112 {
113 "test3 ld_imm64",
114 .insns = {
115 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
116 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
117 BPF_LD_IMM64(BPF_REG_0, 0),
118 BPF_LD_IMM64(BPF_REG_0, 0),
119 BPF_LD_IMM64(BPF_REG_0, 1),
120 BPF_LD_IMM64(BPF_REG_0, 1),
121 BPF_EXIT_INSN(),
122 },
123 .errstr = "invalid bpf_ld_imm64 insn",
124 .result = REJECT,
125 },
126 {
127 "test4 ld_imm64",
128 .insns = {
129 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
130 BPF_EXIT_INSN(),
131 },
132 .errstr = "invalid bpf_ld_imm64 insn",
133 .result = REJECT,
134 },
135 {
136 "test5 ld_imm64",
137 .insns = {
138 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
139 },
140 .errstr = "invalid bpf_ld_imm64 insn",
141 .result = REJECT,
142 },
143 {
144 "no bpf_exit",
145 .insns = {
146 BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2),
147 },
148 .errstr = "jump out of range",
149 .result = REJECT,
150 },
151 {
152 "loop (back-edge)",
153 .insns = {
154 BPF_JMP_IMM(BPF_JA, 0, 0, -1),
155 BPF_EXIT_INSN(),
156 },
157 .errstr = "back-edge",
158 .result = REJECT,
159 },
160 {
161 "loop2 (back-edge)",
162 .insns = {
163 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
164 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
165 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
166 BPF_JMP_IMM(BPF_JA, 0, 0, -4),
167 BPF_EXIT_INSN(),
168 },
169 .errstr = "back-edge",
170 .result = REJECT,
171 },
172 {
173 "conditional loop",
174 .insns = {
175 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
176 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
177 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
178 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3),
179 BPF_EXIT_INSN(),
180 },
181 .errstr = "back-edge",
182 .result = REJECT,
183 },
184 {
185 "read uninitialized register",
186 .insns = {
187 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
188 BPF_EXIT_INSN(),
189 },
190 .errstr = "R2 !read_ok",
191 .result = REJECT,
192 },
193 {
194 "read invalid register",
195 .insns = {
196 BPF_MOV64_REG(BPF_REG_0, -1),
197 BPF_EXIT_INSN(),
198 },
199 .errstr = "R15 is invalid",
200 .result = REJECT,
201 },
202 {
203 "program doesn't init R0 before exit",
204 .insns = {
205 BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
206 BPF_EXIT_INSN(),
207 },
208 .errstr = "R0 !read_ok",
209 .result = REJECT,
210 },
211 {
Alexei Starovoitov32bf08a2014-10-20 14:54:57 -0700212 "program doesn't init R0 before exit in all branches",
213 .insns = {
214 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
215 BPF_MOV64_IMM(BPF_REG_0, 1),
216 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
217 BPF_EXIT_INSN(),
218 },
219 .errstr = "R0 !read_ok",
220 .result = REJECT,
221 },
222 {
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700223 "stack out of bounds",
224 .insns = {
225 BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0),
226 BPF_EXIT_INSN(),
227 },
228 .errstr = "invalid stack",
229 .result = REJECT,
230 },
231 {
232 "invalid call insn1",
233 .insns = {
234 BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0),
235 BPF_EXIT_INSN(),
236 },
237 .errstr = "BPF_CALL uses reserved",
238 .result = REJECT,
239 },
240 {
241 "invalid call insn2",
242 .insns = {
243 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0),
244 BPF_EXIT_INSN(),
245 },
246 .errstr = "BPF_CALL uses reserved",
247 .result = REJECT,
248 },
249 {
250 "invalid function call",
251 .insns = {
252 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567),
253 BPF_EXIT_INSN(),
254 },
255 .errstr = "invalid func 1234567",
256 .result = REJECT,
257 },
258 {
259 "uninitialized stack1",
260 .insns = {
261 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
262 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
263 BPF_LD_MAP_FD(BPF_REG_1, 0),
Alexei Starovoitov7943c0f2014-11-13 17:36:50 -0800264 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700265 BPF_EXIT_INSN(),
266 },
267 .fixup = {2},
268 .errstr = "invalid indirect read from stack",
269 .result = REJECT,
270 },
271 {
272 "uninitialized stack2",
273 .insns = {
274 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
275 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8),
276 BPF_EXIT_INSN(),
277 },
278 .errstr = "invalid read from stack",
279 .result = REJECT,
280 },
281 {
282 "check valid spill/fill",
283 .insns = {
284 /* spill R1(ctx) into stack */
285 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
286
287 /* fill it back into R2 */
288 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
289
290 /* should be able to access R0 = *(R2 + 8) */
Daniel Borkmannf91fe172015-03-01 12:31:41 +0100291 /* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
292 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700293 BPF_EXIT_INSN(),
294 },
295 .result = ACCEPT,
296 },
297 {
298 "check corrupted spill/fill",
299 .insns = {
300 /* spill R1(ctx) into stack */
301 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
302
303 /* mess up with R1 pointer on stack */
304 BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
305
306 /* fill back into R0 should fail */
307 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
308
309 BPF_EXIT_INSN(),
310 },
311 .errstr = "corrupted spill",
312 .result = REJECT,
313 },
314 {
315 "invalid src register in STX",
316 .insns = {
317 BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
318 BPF_EXIT_INSN(),
319 },
320 .errstr = "R15 is invalid",
321 .result = REJECT,
322 },
323 {
324 "invalid dst register in STX",
325 .insns = {
326 BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
327 BPF_EXIT_INSN(),
328 },
329 .errstr = "R14 is invalid",
330 .result = REJECT,
331 },
332 {
333 "invalid dst register in ST",
334 .insns = {
335 BPF_ST_MEM(BPF_B, 14, -1, -1),
336 BPF_EXIT_INSN(),
337 },
338 .errstr = "R14 is invalid",
339 .result = REJECT,
340 },
341 {
342 "invalid src register in LDX",
343 .insns = {
344 BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
345 BPF_EXIT_INSN(),
346 },
347 .errstr = "R12 is invalid",
348 .result = REJECT,
349 },
350 {
351 "invalid dst register in LDX",
352 .insns = {
353 BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
354 BPF_EXIT_INSN(),
355 },
356 .errstr = "R11 is invalid",
357 .result = REJECT,
358 },
359 {
360 "junk insn",
361 .insns = {
362 BPF_RAW_INSN(0, 0, 0, 0, 0),
363 BPF_EXIT_INSN(),
364 },
365 .errstr = "invalid BPF_LD_IMM",
366 .result = REJECT,
367 },
368 {
369 "junk insn2",
370 .insns = {
371 BPF_RAW_INSN(1, 0, 0, 0, 0),
372 BPF_EXIT_INSN(),
373 },
374 .errstr = "BPF_LDX uses reserved fields",
375 .result = REJECT,
376 },
377 {
378 "junk insn3",
379 .insns = {
380 BPF_RAW_INSN(-1, 0, 0, 0, 0),
381 BPF_EXIT_INSN(),
382 },
383 .errstr = "invalid BPF_ALU opcode f0",
384 .result = REJECT,
385 },
386 {
387 "junk insn4",
388 .insns = {
389 BPF_RAW_INSN(-1, -1, -1, -1, -1),
390 BPF_EXIT_INSN(),
391 },
392 .errstr = "invalid BPF_ALU opcode f0",
393 .result = REJECT,
394 },
395 {
396 "junk insn5",
397 .insns = {
398 BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
399 BPF_EXIT_INSN(),
400 },
401 .errstr = "BPF_ALU uses reserved fields",
402 .result = REJECT,
403 },
404 {
405 "misaligned read from stack",
406 .insns = {
407 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
408 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
409 BPF_EXIT_INSN(),
410 },
411 .errstr = "misaligned access",
412 .result = REJECT,
413 },
414 {
415 "invalid map_fd for function call",
416 .insns = {
417 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
418 BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
419 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
420 BPF_LD_MAP_FD(BPF_REG_1, 0),
Alexei Starovoitov7943c0f2014-11-13 17:36:50 -0800421 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700422 BPF_EXIT_INSN(),
423 },
424 .errstr = "fd 0 is not pointing to valid bpf_map",
425 .result = REJECT,
426 },
427 {
428 "don't check return value before access",
429 .insns = {
430 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
431 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
432 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
433 BPF_LD_MAP_FD(BPF_REG_1, 0),
Alexei Starovoitov7943c0f2014-11-13 17:36:50 -0800434 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700435 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
436 BPF_EXIT_INSN(),
437 },
438 .fixup = {3},
439 .errstr = "R0 invalid mem access 'map_value_or_null'",
440 .result = REJECT,
441 },
442 {
443 "access memory with incorrect alignment",
444 .insns = {
445 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
446 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
447 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
448 BPF_LD_MAP_FD(BPF_REG_1, 0),
Alexei Starovoitov7943c0f2014-11-13 17:36:50 -0800449 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700450 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
451 BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
452 BPF_EXIT_INSN(),
453 },
454 .fixup = {3},
455 .errstr = "misaligned access",
456 .result = REJECT,
457 },
458 {
459 "sometimes access memory with incorrect alignment",
460 .insns = {
461 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
462 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
463 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
464 BPF_LD_MAP_FD(BPF_REG_1, 0),
Alexei Starovoitov7943c0f2014-11-13 17:36:50 -0800465 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700466 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
467 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
468 BPF_EXIT_INSN(),
469 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
470 BPF_EXIT_INSN(),
471 },
472 .fixup = {3},
473 .errstr = "R0 invalid mem access",
474 .result = REJECT,
475 },
Alexei Starovoitovfd10c2e2014-09-29 18:50:02 -0700476 {
477 "jump test 1",
478 .insns = {
479 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
480 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
481 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
482 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
483 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
484 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
485 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
486 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
487 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
488 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
489 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
490 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
491 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
492 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
493 BPF_MOV64_IMM(BPF_REG_0, 0),
494 BPF_EXIT_INSN(),
495 },
496 .result = ACCEPT,
497 },
498 {
499 "jump test 2",
500 .insns = {
501 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
502 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
503 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
504 BPF_JMP_IMM(BPF_JA, 0, 0, 14),
505 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
506 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
507 BPF_JMP_IMM(BPF_JA, 0, 0, 11),
508 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
509 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
510 BPF_JMP_IMM(BPF_JA, 0, 0, 8),
511 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
512 BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
513 BPF_JMP_IMM(BPF_JA, 0, 0, 5),
514 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
515 BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
516 BPF_JMP_IMM(BPF_JA, 0, 0, 2),
517 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
518 BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
519 BPF_MOV64_IMM(BPF_REG_0, 0),
520 BPF_EXIT_INSN(),
521 },
522 .result = ACCEPT,
523 },
524 {
525 "jump test 3",
526 .insns = {
527 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
528 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
529 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
530 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
531 BPF_JMP_IMM(BPF_JA, 0, 0, 19),
532 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
533 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
534 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
535 BPF_JMP_IMM(BPF_JA, 0, 0, 15),
536 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
537 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
538 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
539 BPF_JMP_IMM(BPF_JA, 0, 0, 11),
540 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
541 BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
542 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
543 BPF_JMP_IMM(BPF_JA, 0, 0, 7),
544 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
545 BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
546 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
547 BPF_JMP_IMM(BPF_JA, 0, 0, 3),
548 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
549 BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
550 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
551 BPF_LD_MAP_FD(BPF_REG_1, 0),
Alexei Starovoitov7943c0f2014-11-13 17:36:50 -0800552 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
Alexei Starovoitovfd10c2e2014-09-29 18:50:02 -0700553 BPF_EXIT_INSN(),
554 },
555 .fixup = {24},
556 .result = ACCEPT,
557 },
558 {
559 "jump test 4",
560 .insns = {
561 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
562 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
563 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
564 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
565 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
566 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
567 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
568 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
569 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
570 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
571 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
572 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
573 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
574 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
575 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
576 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
577 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
578 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
579 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
580 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
581 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
582 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
583 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
584 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
585 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
586 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
587 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
588 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
589 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
590 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
591 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
592 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
593 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
594 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
595 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
596 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
597 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
598 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
599 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
600 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
601 BPF_MOV64_IMM(BPF_REG_0, 0),
602 BPF_EXIT_INSN(),
603 },
604 .result = ACCEPT,
605 },
Alexei Starovoitov342ded42014-10-28 15:11:42 -0700606 {
607 "jump test 5",
608 .insns = {
609 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
610 BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
611 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
612 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
613 BPF_JMP_IMM(BPF_JA, 0, 0, 2),
614 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
615 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
616 BPF_MOV64_IMM(BPF_REG_0, 0),
617 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
618 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
619 BPF_JMP_IMM(BPF_JA, 0, 0, 2),
620 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
621 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
622 BPF_MOV64_IMM(BPF_REG_0, 0),
623 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
624 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
625 BPF_JMP_IMM(BPF_JA, 0, 0, 2),
626 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
627 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
628 BPF_MOV64_IMM(BPF_REG_0, 0),
629 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
630 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
631 BPF_JMP_IMM(BPF_JA, 0, 0, 2),
632 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
633 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
634 BPF_MOV64_IMM(BPF_REG_0, 0),
635 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
636 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
637 BPF_JMP_IMM(BPF_JA, 0, 0, 2),
638 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
639 BPF_JMP_IMM(BPF_JA, 0, 0, 0),
640 BPF_MOV64_IMM(BPF_REG_0, 0),
641 BPF_EXIT_INSN(),
642 },
643 .result = ACCEPT,
644 },
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700645};
646
647static int probe_filter_length(struct bpf_insn *fp)
648{
649 int len = 0;
650
651 for (len = MAX_INSNS - 1; len > 0; --len)
652 if (fp[len].code != 0 || fp[len].imm != 0)
653 break;
654
655 return len + 1;
656}
657
658static int create_map(void)
659{
660 long long key, value = 0;
661 int map_fd;
662
Alexei Starovoitov7943c0f2014-11-13 17:36:50 -0800663 map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1024);
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700664 if (map_fd < 0) {
665 printf("failed to create map '%s'\n", strerror(errno));
666 }
667
668 return map_fd;
669}
670
671static int test(void)
672{
Alexei Starovoitov342ded42014-10-28 15:11:42 -0700673 int prog_fd, i, pass_cnt = 0, err_cnt = 0;
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700674
675 for (i = 0; i < ARRAY_SIZE(tests); i++) {
676 struct bpf_insn *prog = tests[i].insns;
677 int prog_len = probe_filter_length(prog);
678 int *fixup = tests[i].fixup;
679 int map_fd = -1;
680
681 if (*fixup) {
682 map_fd = create_map();
683
684 do {
685 prog[*fixup].imm = map_fd;
686 fixup++;
687 } while (*fixup);
688 }
689 printf("#%d %s ", i, tests[i].descr);
690
Daniel Borkmannf91fe172015-03-01 12:31:41 +0100691 prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog,
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700692 prog_len * sizeof(struct bpf_insn),
693 "GPL");
694
695 if (tests[i].result == ACCEPT) {
696 if (prog_fd < 0) {
697 printf("FAIL\nfailed to load prog '%s'\n",
698 strerror(errno));
699 printf("%s", bpf_log_buf);
Alexei Starovoitov342ded42014-10-28 15:11:42 -0700700 err_cnt++;
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700701 goto fail;
702 }
703 } else {
704 if (prog_fd >= 0) {
705 printf("FAIL\nunexpected success to load\n");
706 printf("%s", bpf_log_buf);
Alexei Starovoitov342ded42014-10-28 15:11:42 -0700707 err_cnt++;
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700708 goto fail;
709 }
710 if (strstr(bpf_log_buf, tests[i].errstr) == 0) {
711 printf("FAIL\nunexpected error message: %s",
712 bpf_log_buf);
Alexei Starovoitov342ded42014-10-28 15:11:42 -0700713 err_cnt++;
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700714 goto fail;
715 }
716 }
717
Alexei Starovoitov342ded42014-10-28 15:11:42 -0700718 pass_cnt++;
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700719 printf("OK\n");
720fail:
721 if (map_fd >= 0)
722 close(map_fd);
723 close(prog_fd);
724
725 }
Alexei Starovoitov342ded42014-10-28 15:11:42 -0700726 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
Alexei Starovoitov3c731eb2014-09-26 00:17:07 -0700727
728 return 0;
729}
730
731int main(void)
732{
733 return test();
734}