]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - samples/bpf/test_verifier.c
2 * Testsuite for eBPF verifier
4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
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.
12 #include <linux/bpf.h>
14 #include <linux/unistd.h>
16 #include <linux/filter.h>
20 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
24 struct bpf_insn insns
[MAX_INSNS
];
33 static struct bpf_test tests
[] = {
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
),
54 .errstr
= "unreachable",
60 BPF_JMP_IMM(BPF_JA
, 0, 0, 1),
61 BPF_JMP_IMM(BPF_JA
, 0, 0, 0),
64 .errstr
= "unreachable",
70 BPF_JMP_IMM(BPF_JA
, 0, 0, 1),
73 .errstr
= "jump out of range",
79 BPF_JMP_IMM(BPF_JA
, 0, 0, -2),
82 .errstr
= "jump out of range",
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),
96 .errstr
= "invalid BPF_LD_IMM insn",
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),
109 .errstr
= "invalid BPF_LD_IMM insn",
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),
123 .errstr
= "invalid bpf_ld_imm64 insn",
129 BPF_RAW_INSN(BPF_LD
| BPF_IMM
| BPF_DW
, 0, 0, 0, 0),
132 .errstr
= "invalid bpf_ld_imm64 insn",
138 BPF_RAW_INSN(BPF_LD
| BPF_IMM
| BPF_DW
, 0, 0, 0, 0),
140 .errstr
= "invalid bpf_ld_imm64 insn",
146 BPF_ALU64_REG(BPF_MOV
, BPF_REG_0
, BPF_REG_2
),
148 .errstr
= "jump out of range",
154 BPF_JMP_IMM(BPF_JA
, 0, 0, -1),
157 .errstr
= "back-edge",
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),
169 .errstr
= "back-edge",
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),
181 .errstr
= "back-edge",
185 "read uninitialized register",
187 BPF_MOV64_REG(BPF_REG_0
, BPF_REG_2
),
190 .errstr
= "R2 !read_ok",
194 "read invalid register",
196 BPF_MOV64_REG(BPF_REG_0
, -1),
199 .errstr
= "R15 is invalid",
203 "program doesn't init R0 before exit",
205 BPF_ALU64_REG(BPF_MOV
, BPF_REG_2
, BPF_REG_1
),
208 .errstr
= "R0 !read_ok",
212 "stack out of bounds",
214 BPF_ST_MEM(BPF_DW
, BPF_REG_10
, 8, 0),
217 .errstr
= "invalid stack",
221 "invalid call insn1",
223 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
| BPF_X
, 0, 0, 0, 0),
226 .errstr
= "BPF_CALL uses reserved",
230 "invalid call insn2",
232 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 1, 0),
235 .errstr
= "BPF_CALL uses reserved",
239 "invalid function call",
241 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, 1234567),
244 .errstr
= "invalid func 1234567",
248 "uninitialized stack1",
250 BPF_MOV64_REG(BPF_REG_2
, BPF_REG_10
),
251 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_2
, -8),
252 BPF_LD_MAP_FD(BPF_REG_1
, 0),
253 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_unspec
),
257 .errstr
= "invalid indirect read from stack",
261 "uninitialized stack2",
263 BPF_MOV64_REG(BPF_REG_2
, BPF_REG_10
),
264 BPF_LDX_MEM(BPF_DW
, BPF_REG_0
, BPF_REG_2
, -8),
267 .errstr
= "invalid read from stack",
271 "check valid spill/fill",
273 /* spill R1(ctx) into stack */
274 BPF_STX_MEM(BPF_DW
, BPF_REG_10
, BPF_REG_1
, -8),
276 /* fill it back into R2 */
277 BPF_LDX_MEM(BPF_DW
, BPF_REG_2
, BPF_REG_10
, -8),
279 /* should be able to access R0 = *(R2 + 8) */
280 BPF_LDX_MEM(BPF_DW
, BPF_REG_0
, BPF_REG_2
, 8),
286 "check corrupted spill/fill",
288 /* spill R1(ctx) into stack */
289 BPF_STX_MEM(BPF_DW
, BPF_REG_10
, BPF_REG_1
, -8),
291 /* mess up with R1 pointer on stack */
292 BPF_ST_MEM(BPF_B
, BPF_REG_10
, -7, 0x23),
294 /* fill back into R0 should fail */
295 BPF_LDX_MEM(BPF_DW
, BPF_REG_0
, BPF_REG_10
, -8),
299 .errstr
= "corrupted spill",
303 "invalid src register in STX",
305 BPF_STX_MEM(BPF_B
, BPF_REG_10
, -1, -1),
308 .errstr
= "R15 is invalid",
312 "invalid dst register in STX",
314 BPF_STX_MEM(BPF_B
, 14, BPF_REG_10
, -1),
317 .errstr
= "R14 is invalid",
321 "invalid dst register in ST",
323 BPF_ST_MEM(BPF_B
, 14, -1, -1),
326 .errstr
= "R14 is invalid",
330 "invalid src register in LDX",
332 BPF_LDX_MEM(BPF_B
, BPF_REG_0
, 12, 0),
335 .errstr
= "R12 is invalid",
339 "invalid dst register in LDX",
341 BPF_LDX_MEM(BPF_B
, 11, BPF_REG_1
, 0),
344 .errstr
= "R11 is invalid",
350 BPF_RAW_INSN(0, 0, 0, 0, 0),
353 .errstr
= "invalid BPF_LD_IMM",
359 BPF_RAW_INSN(1, 0, 0, 0, 0),
362 .errstr
= "BPF_LDX uses reserved fields",
368 BPF_RAW_INSN(-1, 0, 0, 0, 0),
371 .errstr
= "invalid BPF_ALU opcode f0",
377 BPF_RAW_INSN(-1, -1, -1, -1, -1),
380 .errstr
= "invalid BPF_ALU opcode f0",
386 BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
389 .errstr
= "BPF_ALU uses reserved fields",
393 "misaligned read from stack",
395 BPF_MOV64_REG(BPF_REG_2
, BPF_REG_10
),
396 BPF_LDX_MEM(BPF_DW
, BPF_REG_0
, BPF_REG_2
, -4),
399 .errstr
= "misaligned access",
403 "invalid map_fd for function call",
405 BPF_ST_MEM(BPF_DW
, BPF_REG_10
, -8, 0),
406 BPF_ALU64_REG(BPF_MOV
, BPF_REG_2
, BPF_REG_10
),
407 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_2
, -8),
408 BPF_LD_MAP_FD(BPF_REG_1
, 0),
409 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_unspec
),
412 .errstr
= "fd 0 is not pointing to valid bpf_map",
416 "don't check return value before access",
418 BPF_ST_MEM(BPF_DW
, BPF_REG_10
, -8, 0),
419 BPF_MOV64_REG(BPF_REG_2
, BPF_REG_10
),
420 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_2
, -8),
421 BPF_LD_MAP_FD(BPF_REG_1
, 0),
422 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_unspec
),
423 BPF_ST_MEM(BPF_DW
, BPF_REG_0
, 0, 0),
427 .errstr
= "R0 invalid mem access 'map_value_or_null'",
431 "access memory with incorrect alignment",
433 BPF_ST_MEM(BPF_DW
, BPF_REG_10
, -8, 0),
434 BPF_MOV64_REG(BPF_REG_2
, BPF_REG_10
),
435 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_2
, -8),
436 BPF_LD_MAP_FD(BPF_REG_1
, 0),
437 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_unspec
),
438 BPF_JMP_IMM(BPF_JEQ
, BPF_REG_0
, 0, 1),
439 BPF_ST_MEM(BPF_DW
, BPF_REG_0
, 4, 0),
443 .errstr
= "misaligned access",
447 "sometimes access memory with incorrect alignment",
449 BPF_ST_MEM(BPF_DW
, BPF_REG_10
, -8, 0),
450 BPF_MOV64_REG(BPF_REG_2
, BPF_REG_10
),
451 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_2
, -8),
452 BPF_LD_MAP_FD(BPF_REG_1
, 0),
453 BPF_RAW_INSN(BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_unspec
),
454 BPF_JMP_IMM(BPF_JEQ
, BPF_REG_0
, 0, 2),
455 BPF_ST_MEM(BPF_DW
, BPF_REG_0
, 0, 0),
457 BPF_ST_MEM(BPF_DW
, BPF_REG_0
, 0, 1),
461 .errstr
= "R0 invalid mem access",
466 static int probe_filter_length(struct bpf_insn
*fp
)
470 for (len
= MAX_INSNS
- 1; len
> 0; --len
)
471 if (fp
[len
].code
!= 0 || fp
[len
].imm
!= 0)
477 static int create_map(void)
479 long long key
, value
= 0;
482 map_fd
= bpf_create_map(BPF_MAP_TYPE_UNSPEC
, sizeof(key
), sizeof(value
), 1024);
484 printf("failed to create map '%s'\n", strerror(errno
));
490 static int test(void)
494 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
495 struct bpf_insn
*prog
= tests
[i
].insns
;
496 int prog_len
= probe_filter_length(prog
);
497 int *fixup
= tests
[i
].fixup
;
501 map_fd
= create_map();
504 prog
[*fixup
].imm
= map_fd
;
508 printf("#%d %s ", i
, tests
[i
].descr
);
510 prog_fd
= bpf_prog_load(BPF_PROG_TYPE_UNSPEC
, prog
,
511 prog_len
* sizeof(struct bpf_insn
),
514 if (tests
[i
].result
== ACCEPT
) {
516 printf("FAIL\nfailed to load prog '%s'\n",
518 printf("%s", bpf_log_buf
);
523 printf("FAIL\nunexpected success to load\n");
524 printf("%s", bpf_log_buf
);
527 if (strstr(bpf_log_buf
, tests
[i
].errstr
) == 0) {
528 printf("FAIL\nunexpected error message: %s",