]> git.karo-electronics.de Git - karo-tx-linux.git/blob - samples/bpf/test_verifier.c
ebpf: remove kernel test stubs
[karo-tx-linux.git] / samples / bpf / test_verifier.c
1 /*
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
22 struct 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
33 static 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         {
212                 "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         {
223                 "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),
264                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
265                         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) */
291                         /* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
292                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
293                         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),
421                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
422                         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),
434                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
435                         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),
449                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
450                         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),
465                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
466                         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         },
476         {
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),
552                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
553                         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         },
606         {
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         },
645 };
646
647 static 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
658 static int create_map(void)
659 {
660         long long key, value = 0;
661         int map_fd;
662
663         map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1024);
664         if (map_fd < 0) {
665                 printf("failed to create map '%s'\n", strerror(errno));
666         }
667
668         return map_fd;
669 }
670
671 static int test(void)
672 {
673         int prog_fd, i, pass_cnt = 0, err_cnt = 0;
674
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
691                 prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog,
692                                         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);
700                                 err_cnt++;
701                                 goto fail;
702                         }
703                 } else {
704                         if (prog_fd >= 0) {
705                                 printf("FAIL\nunexpected success to load\n");
706                                 printf("%s", bpf_log_buf);
707                                 err_cnt++;
708                                 goto fail;
709                         }
710                         if (strstr(bpf_log_buf, tests[i].errstr) == 0) {
711                                 printf("FAIL\nunexpected error message: %s",
712                                        bpf_log_buf);
713                                 err_cnt++;
714                                 goto fail;
715                         }
716                 }
717
718                 pass_cnt++;
719                 printf("OK\n");
720 fail:
721                 if (map_fd >= 0)
722                         close(map_fd);
723                 close(prog_fd);
724
725         }
726         printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
727
728         return 0;
729 }
730
731 int main(void)
732 {
733         return test();
734 }