Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/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_EXIT_INSN(),
293                 },
294                 .result = ACCEPT,
295         },
296         {
297                 "check corrupted spill/fill",
298                 .insns = {
299                         /* spill R1(ctx) into stack */
300                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
301
302                         /* mess up with R1 pointer on stack */
303                         BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
304
305                         /* fill back into R0 should fail */
306                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
307
308                         BPF_EXIT_INSN(),
309                 },
310                 .errstr = "corrupted spill",
311                 .result = REJECT,
312         },
313         {
314                 "invalid src register in STX",
315                 .insns = {
316                         BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
317                         BPF_EXIT_INSN(),
318                 },
319                 .errstr = "R15 is invalid",
320                 .result = REJECT,
321         },
322         {
323                 "invalid dst register in STX",
324                 .insns = {
325                         BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
326                         BPF_EXIT_INSN(),
327                 },
328                 .errstr = "R14 is invalid",
329                 .result = REJECT,
330         },
331         {
332                 "invalid dst register in ST",
333                 .insns = {
334                         BPF_ST_MEM(BPF_B, 14, -1, -1),
335                         BPF_EXIT_INSN(),
336                 },
337                 .errstr = "R14 is invalid",
338                 .result = REJECT,
339         },
340         {
341                 "invalid src register in LDX",
342                 .insns = {
343                         BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
344                         BPF_EXIT_INSN(),
345                 },
346                 .errstr = "R12 is invalid",
347                 .result = REJECT,
348         },
349         {
350                 "invalid dst register in LDX",
351                 .insns = {
352                         BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
353                         BPF_EXIT_INSN(),
354                 },
355                 .errstr = "R11 is invalid",
356                 .result = REJECT,
357         },
358         {
359                 "junk insn",
360                 .insns = {
361                         BPF_RAW_INSN(0, 0, 0, 0, 0),
362                         BPF_EXIT_INSN(),
363                 },
364                 .errstr = "invalid BPF_LD_IMM",
365                 .result = REJECT,
366         },
367         {
368                 "junk insn2",
369                 .insns = {
370                         BPF_RAW_INSN(1, 0, 0, 0, 0),
371                         BPF_EXIT_INSN(),
372                 },
373                 .errstr = "BPF_LDX uses reserved fields",
374                 .result = REJECT,
375         },
376         {
377                 "junk insn3",
378                 .insns = {
379                         BPF_RAW_INSN(-1, 0, 0, 0, 0),
380                         BPF_EXIT_INSN(),
381                 },
382                 .errstr = "invalid BPF_ALU opcode f0",
383                 .result = REJECT,
384         },
385         {
386                 "junk insn4",
387                 .insns = {
388                         BPF_RAW_INSN(-1, -1, -1, -1, -1),
389                         BPF_EXIT_INSN(),
390                 },
391                 .errstr = "invalid BPF_ALU opcode f0",
392                 .result = REJECT,
393         },
394         {
395                 "junk insn5",
396                 .insns = {
397                         BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
398                         BPF_EXIT_INSN(),
399                 },
400                 .errstr = "BPF_ALU uses reserved fields",
401                 .result = REJECT,
402         },
403         {
404                 "misaligned read from stack",
405                 .insns = {
406                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
407                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
408                         BPF_EXIT_INSN(),
409                 },
410                 .errstr = "misaligned access",
411                 .result = REJECT,
412         },
413         {
414                 "invalid map_fd for function call",
415                 .insns = {
416                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
417                         BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
418                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
419                         BPF_LD_MAP_FD(BPF_REG_1, 0),
420                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
421                         BPF_EXIT_INSN(),
422                 },
423                 .errstr = "fd 0 is not pointing to valid bpf_map",
424                 .result = REJECT,
425         },
426         {
427                 "don't check return value before access",
428                 .insns = {
429                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
430                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
431                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
432                         BPF_LD_MAP_FD(BPF_REG_1, 0),
433                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
434                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
435                         BPF_EXIT_INSN(),
436                 },
437                 .fixup = {3},
438                 .errstr = "R0 invalid mem access 'map_value_or_null'",
439                 .result = REJECT,
440         },
441         {
442                 "access memory with incorrect alignment",
443                 .insns = {
444                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
445                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
446                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
447                         BPF_LD_MAP_FD(BPF_REG_1, 0),
448                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
449                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
450                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
451                         BPF_EXIT_INSN(),
452                 },
453                 .fixup = {3},
454                 .errstr = "misaligned access",
455                 .result = REJECT,
456         },
457         {
458                 "sometimes access memory with incorrect alignment",
459                 .insns = {
460                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
461                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
462                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
463                         BPF_LD_MAP_FD(BPF_REG_1, 0),
464                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
465                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
466                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
467                         BPF_EXIT_INSN(),
468                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
469                         BPF_EXIT_INSN(),
470                 },
471                 .fixup = {3},
472                 .errstr = "R0 invalid mem access",
473                 .result = REJECT,
474         },
475         {
476                 "jump test 1",
477                 .insns = {
478                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
479                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
480                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
481                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
482                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
483                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
484                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
485                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
486                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
487                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
488                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
489                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
490                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
491                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
492                         BPF_MOV64_IMM(BPF_REG_0, 0),
493                         BPF_EXIT_INSN(),
494                 },
495                 .result = ACCEPT,
496         },
497         {
498                 "jump test 2",
499                 .insns = {
500                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
501                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
502                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
503                         BPF_JMP_IMM(BPF_JA, 0, 0, 14),
504                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
505                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
506                         BPF_JMP_IMM(BPF_JA, 0, 0, 11),
507                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
508                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
509                         BPF_JMP_IMM(BPF_JA, 0, 0, 8),
510                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
511                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
512                         BPF_JMP_IMM(BPF_JA, 0, 0, 5),
513                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
514                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
515                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
516                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
517                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
518                         BPF_MOV64_IMM(BPF_REG_0, 0),
519                         BPF_EXIT_INSN(),
520                 },
521                 .result = ACCEPT,
522         },
523         {
524                 "jump test 3",
525                 .insns = {
526                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
527                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
528                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
529                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
530                         BPF_JMP_IMM(BPF_JA, 0, 0, 19),
531                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
532                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
533                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
534                         BPF_JMP_IMM(BPF_JA, 0, 0, 15),
535                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
536                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
537                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
538                         BPF_JMP_IMM(BPF_JA, 0, 0, 11),
539                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
540                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
541                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
542                         BPF_JMP_IMM(BPF_JA, 0, 0, 7),
543                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
544                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
545                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
546                         BPF_JMP_IMM(BPF_JA, 0, 0, 3),
547                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
548                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
549                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
550                         BPF_LD_MAP_FD(BPF_REG_1, 0),
551                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
552                         BPF_EXIT_INSN(),
553                 },
554                 .fixup = {24},
555                 .result = ACCEPT,
556         },
557         {
558                 "jump test 4",
559                 .insns = {
560                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
561                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
562                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
563                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
564                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
565                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
566                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
567                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
568                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
569                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
570                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
571                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
572                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
573                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
574                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
575                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
576                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
577                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
578                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
579                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
580                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
581                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
582                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
583                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
584                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
585                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
586                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
587                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
588                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
589                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
590                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
591                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
592                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
593                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
594                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
595                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
596                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
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_MOV64_IMM(BPF_REG_0, 0),
601                         BPF_EXIT_INSN(),
602                 },
603                 .result = ACCEPT,
604         },
605         {
606                 "jump test 5",
607                 .insns = {
608                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
609                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
610                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
611                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
612                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
613                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
614                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
615                         BPF_MOV64_IMM(BPF_REG_0, 0),
616                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
617                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
618                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
619                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
620                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
621                         BPF_MOV64_IMM(BPF_REG_0, 0),
622                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
623                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
624                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
625                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
626                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
627                         BPF_MOV64_IMM(BPF_REG_0, 0),
628                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
629                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
630                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
631                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
632                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
633                         BPF_MOV64_IMM(BPF_REG_0, 0),
634                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
635                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
636                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
637                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
638                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
639                         BPF_MOV64_IMM(BPF_REG_0, 0),
640                         BPF_EXIT_INSN(),
641                 },
642                 .result = ACCEPT,
643         },
644 };
645
646 static int probe_filter_length(struct bpf_insn *fp)
647 {
648         int len = 0;
649
650         for (len = MAX_INSNS - 1; len > 0; --len)
651                 if (fp[len].code != 0 || fp[len].imm != 0)
652                         break;
653
654         return len + 1;
655 }
656
657 static int create_map(void)
658 {
659         long long key, value = 0;
660         int map_fd;
661
662         map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1024);
663         if (map_fd < 0) {
664                 printf("failed to create map '%s'\n", strerror(errno));
665         }
666
667         return map_fd;
668 }
669
670 static int test(void)
671 {
672         int prog_fd, i, pass_cnt = 0, err_cnt = 0;
673
674         for (i = 0; i < ARRAY_SIZE(tests); i++) {
675                 struct bpf_insn *prog = tests[i].insns;
676                 int prog_len = probe_filter_length(prog);
677                 int *fixup = tests[i].fixup;
678                 int map_fd = -1;
679
680                 if (*fixup) {
681                         map_fd = create_map();
682
683                         do {
684                                 prog[*fixup].imm = map_fd;
685                                 fixup++;
686                         } while (*fixup);
687                 }
688                 printf("#%d %s ", i, tests[i].descr);
689
690                 prog_fd = bpf_prog_load(BPF_PROG_TYPE_UNSPEC, prog,
691                                         prog_len * sizeof(struct bpf_insn),
692                                         "GPL");
693
694                 if (tests[i].result == ACCEPT) {
695                         if (prog_fd < 0) {
696                                 printf("FAIL\nfailed to load prog '%s'\n",
697                                        strerror(errno));
698                                 printf("%s", bpf_log_buf);
699                                 err_cnt++;
700                                 goto fail;
701                         }
702                 } else {
703                         if (prog_fd >= 0) {
704                                 printf("FAIL\nunexpected success to load\n");
705                                 printf("%s", bpf_log_buf);
706                                 err_cnt++;
707                                 goto fail;
708                         }
709                         if (strstr(bpf_log_buf, tests[i].errstr) == 0) {
710                                 printf("FAIL\nunexpected error message: %s",
711                                        bpf_log_buf);
712                                 err_cnt++;
713                                 goto fail;
714                         }
715                 }
716
717                 pass_cnt++;
718                 printf("OK\n");
719 fail:
720                 if (map_fd >= 0)
721                         close(map_fd);
722                 close(prog_fd);
723
724         }
725         printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
726
727         return 0;
728 }
729
730 int main(void)
731 {
732         return test();
733 }