Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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 <stddef.h>
18 #include "libbpf.h"
19
20 #define MAX_INSNS 512
21 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
22
23 struct bpf_test {
24         const char *descr;
25         struct bpf_insn insns[MAX_INSNS];
26         int fixup[32];
27         const char *errstr;
28         enum {
29                 ACCEPT,
30                 REJECT
31         } result;
32 };
33
34 static struct bpf_test tests[] = {
35         {
36                 "add+sub+mul",
37                 .insns = {
38                         BPF_MOV64_IMM(BPF_REG_1, 1),
39                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 2),
40                         BPF_MOV64_IMM(BPF_REG_2, 3),
41                         BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_2),
42                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1),
43                         BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 3),
44                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
45                         BPF_EXIT_INSN(),
46                 },
47                 .result = ACCEPT,
48         },
49         {
50                 "unreachable",
51                 .insns = {
52                         BPF_EXIT_INSN(),
53                         BPF_EXIT_INSN(),
54                 },
55                 .errstr = "unreachable",
56                 .result = REJECT,
57         },
58         {
59                 "unreachable2",
60                 .insns = {
61                         BPF_JMP_IMM(BPF_JA, 0, 0, 1),
62                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
63                         BPF_EXIT_INSN(),
64                 },
65                 .errstr = "unreachable",
66                 .result = REJECT,
67         },
68         {
69                 "out of range jump",
70                 .insns = {
71                         BPF_JMP_IMM(BPF_JA, 0, 0, 1),
72                         BPF_EXIT_INSN(),
73                 },
74                 .errstr = "jump out of range",
75                 .result = REJECT,
76         },
77         {
78                 "out of range jump2",
79                 .insns = {
80                         BPF_JMP_IMM(BPF_JA, 0, 0, -2),
81                         BPF_EXIT_INSN(),
82                 },
83                 .errstr = "jump out of range",
84                 .result = REJECT,
85         },
86         {
87                 "test1 ld_imm64",
88                 .insns = {
89                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
90                         BPF_LD_IMM64(BPF_REG_0, 0),
91                         BPF_LD_IMM64(BPF_REG_0, 0),
92                         BPF_LD_IMM64(BPF_REG_0, 1),
93                         BPF_LD_IMM64(BPF_REG_0, 1),
94                         BPF_MOV64_IMM(BPF_REG_0, 2),
95                         BPF_EXIT_INSN(),
96                 },
97                 .errstr = "invalid BPF_LD_IMM insn",
98                 .result = REJECT,
99         },
100         {
101                 "test2 ld_imm64",
102                 .insns = {
103                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
104                         BPF_LD_IMM64(BPF_REG_0, 0),
105                         BPF_LD_IMM64(BPF_REG_0, 0),
106                         BPF_LD_IMM64(BPF_REG_0, 1),
107                         BPF_LD_IMM64(BPF_REG_0, 1),
108                         BPF_EXIT_INSN(),
109                 },
110                 .errstr = "invalid BPF_LD_IMM insn",
111                 .result = REJECT,
112         },
113         {
114                 "test3 ld_imm64",
115                 .insns = {
116                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
117                         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
118                         BPF_LD_IMM64(BPF_REG_0, 0),
119                         BPF_LD_IMM64(BPF_REG_0, 0),
120                         BPF_LD_IMM64(BPF_REG_0, 1),
121                         BPF_LD_IMM64(BPF_REG_0, 1),
122                         BPF_EXIT_INSN(),
123                 },
124                 .errstr = "invalid bpf_ld_imm64 insn",
125                 .result = REJECT,
126         },
127         {
128                 "test4 ld_imm64",
129                 .insns = {
130                         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
131                         BPF_EXIT_INSN(),
132                 },
133                 .errstr = "invalid bpf_ld_imm64 insn",
134                 .result = REJECT,
135         },
136         {
137                 "test5 ld_imm64",
138                 .insns = {
139                         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
140                 },
141                 .errstr = "invalid bpf_ld_imm64 insn",
142                 .result = REJECT,
143         },
144         {
145                 "no bpf_exit",
146                 .insns = {
147                         BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2),
148                 },
149                 .errstr = "jump out of range",
150                 .result = REJECT,
151         },
152         {
153                 "loop (back-edge)",
154                 .insns = {
155                         BPF_JMP_IMM(BPF_JA, 0, 0, -1),
156                         BPF_EXIT_INSN(),
157                 },
158                 .errstr = "back-edge",
159                 .result = REJECT,
160         },
161         {
162                 "loop2 (back-edge)",
163                 .insns = {
164                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
165                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
166                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
167                         BPF_JMP_IMM(BPF_JA, 0, 0, -4),
168                         BPF_EXIT_INSN(),
169                 },
170                 .errstr = "back-edge",
171                 .result = REJECT,
172         },
173         {
174                 "conditional loop",
175                 .insns = {
176                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
177                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
178                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
179                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3),
180                         BPF_EXIT_INSN(),
181                 },
182                 .errstr = "back-edge",
183                 .result = REJECT,
184         },
185         {
186                 "read uninitialized register",
187                 .insns = {
188                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
189                         BPF_EXIT_INSN(),
190                 },
191                 .errstr = "R2 !read_ok",
192                 .result = REJECT,
193         },
194         {
195                 "read invalid register",
196                 .insns = {
197                         BPF_MOV64_REG(BPF_REG_0, -1),
198                         BPF_EXIT_INSN(),
199                 },
200                 .errstr = "R15 is invalid",
201                 .result = REJECT,
202         },
203         {
204                 "program doesn't init R0 before exit",
205                 .insns = {
206                         BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
207                         BPF_EXIT_INSN(),
208                 },
209                 .errstr = "R0 !read_ok",
210                 .result = REJECT,
211         },
212         {
213                 "program doesn't init R0 before exit in all branches",
214                 .insns = {
215                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
216                         BPF_MOV64_IMM(BPF_REG_0, 1),
217                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
218                         BPF_EXIT_INSN(),
219                 },
220                 .errstr = "R0 !read_ok",
221                 .result = REJECT,
222         },
223         {
224                 "stack out of bounds",
225                 .insns = {
226                         BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0),
227                         BPF_EXIT_INSN(),
228                 },
229                 .errstr = "invalid stack",
230                 .result = REJECT,
231         },
232         {
233                 "invalid call insn1",
234                 .insns = {
235                         BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0),
236                         BPF_EXIT_INSN(),
237                 },
238                 .errstr = "BPF_CALL uses reserved",
239                 .result = REJECT,
240         },
241         {
242                 "invalid call insn2",
243                 .insns = {
244                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0),
245                         BPF_EXIT_INSN(),
246                 },
247                 .errstr = "BPF_CALL uses reserved",
248                 .result = REJECT,
249         },
250         {
251                 "invalid function call",
252                 .insns = {
253                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567),
254                         BPF_EXIT_INSN(),
255                 },
256                 .errstr = "invalid func 1234567",
257                 .result = REJECT,
258         },
259         {
260                 "uninitialized stack1",
261                 .insns = {
262                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
263                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
264                         BPF_LD_MAP_FD(BPF_REG_1, 0),
265                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
266                         BPF_EXIT_INSN(),
267                 },
268                 .fixup = {2},
269                 .errstr = "invalid indirect read from stack",
270                 .result = REJECT,
271         },
272         {
273                 "uninitialized stack2",
274                 .insns = {
275                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
276                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8),
277                         BPF_EXIT_INSN(),
278                 },
279                 .errstr = "invalid read from stack",
280                 .result = REJECT,
281         },
282         {
283                 "check valid spill/fill",
284                 .insns = {
285                         /* spill R1(ctx) into stack */
286                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
287
288                         /* fill it back into R2 */
289                         BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
290
291                         /* should be able to access R0 = *(R2 + 8) */
292                         /* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
293                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
294                         BPF_EXIT_INSN(),
295                 },
296                 .result = ACCEPT,
297         },
298         {
299                 "check corrupted spill/fill",
300                 .insns = {
301                         /* spill R1(ctx) into stack */
302                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
303
304                         /* mess up with R1 pointer on stack */
305                         BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
306
307                         /* fill back into R0 should fail */
308                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
309
310                         BPF_EXIT_INSN(),
311                 },
312                 .errstr = "corrupted spill",
313                 .result = REJECT,
314         },
315         {
316                 "invalid src register in STX",
317                 .insns = {
318                         BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
319                         BPF_EXIT_INSN(),
320                 },
321                 .errstr = "R15 is invalid",
322                 .result = REJECT,
323         },
324         {
325                 "invalid dst register in STX",
326                 .insns = {
327                         BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
328                         BPF_EXIT_INSN(),
329                 },
330                 .errstr = "R14 is invalid",
331                 .result = REJECT,
332         },
333         {
334                 "invalid dst register in ST",
335                 .insns = {
336                         BPF_ST_MEM(BPF_B, 14, -1, -1),
337                         BPF_EXIT_INSN(),
338                 },
339                 .errstr = "R14 is invalid",
340                 .result = REJECT,
341         },
342         {
343                 "invalid src register in LDX",
344                 .insns = {
345                         BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
346                         BPF_EXIT_INSN(),
347                 },
348                 .errstr = "R12 is invalid",
349                 .result = REJECT,
350         },
351         {
352                 "invalid dst register in LDX",
353                 .insns = {
354                         BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
355                         BPF_EXIT_INSN(),
356                 },
357                 .errstr = "R11 is invalid",
358                 .result = REJECT,
359         },
360         {
361                 "junk insn",
362                 .insns = {
363                         BPF_RAW_INSN(0, 0, 0, 0, 0),
364                         BPF_EXIT_INSN(),
365                 },
366                 .errstr = "invalid BPF_LD_IMM",
367                 .result = REJECT,
368         },
369         {
370                 "junk insn2",
371                 .insns = {
372                         BPF_RAW_INSN(1, 0, 0, 0, 0),
373                         BPF_EXIT_INSN(),
374                 },
375                 .errstr = "BPF_LDX uses reserved fields",
376                 .result = REJECT,
377         },
378         {
379                 "junk insn3",
380                 .insns = {
381                         BPF_RAW_INSN(-1, 0, 0, 0, 0),
382                         BPF_EXIT_INSN(),
383                 },
384                 .errstr = "invalid BPF_ALU opcode f0",
385                 .result = REJECT,
386         },
387         {
388                 "junk insn4",
389                 .insns = {
390                         BPF_RAW_INSN(-1, -1, -1, -1, -1),
391                         BPF_EXIT_INSN(),
392                 },
393                 .errstr = "invalid BPF_ALU opcode f0",
394                 .result = REJECT,
395         },
396         {
397                 "junk insn5",
398                 .insns = {
399                         BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
400                         BPF_EXIT_INSN(),
401                 },
402                 .errstr = "BPF_ALU uses reserved fields",
403                 .result = REJECT,
404         },
405         {
406                 "misaligned read from stack",
407                 .insns = {
408                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
409                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
410                         BPF_EXIT_INSN(),
411                 },
412                 .errstr = "misaligned access",
413                 .result = REJECT,
414         },
415         {
416                 "invalid map_fd for function call",
417                 .insns = {
418                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
419                         BPF_ALU64_REG(BPF_MOV, 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_map_delete_elem),
423                         BPF_EXIT_INSN(),
424                 },
425                 .errstr = "fd 0 is not pointing to valid bpf_map",
426                 .result = REJECT,
427         },
428         {
429                 "don't check return value before access",
430                 .insns = {
431                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
432                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
433                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
434                         BPF_LD_MAP_FD(BPF_REG_1, 0),
435                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
436                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
437                         BPF_EXIT_INSN(),
438                 },
439                 .fixup = {3},
440                 .errstr = "R0 invalid mem access 'map_value_or_null'",
441                 .result = REJECT,
442         },
443         {
444                 "access memory with incorrect alignment",
445                 .insns = {
446                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
447                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
448                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
449                         BPF_LD_MAP_FD(BPF_REG_1, 0),
450                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
451                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
452                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
453                         BPF_EXIT_INSN(),
454                 },
455                 .fixup = {3},
456                 .errstr = "misaligned access",
457                 .result = REJECT,
458         },
459         {
460                 "sometimes access memory with incorrect alignment",
461                 .insns = {
462                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
463                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
464                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
465                         BPF_LD_MAP_FD(BPF_REG_1, 0),
466                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
467                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
468                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
469                         BPF_EXIT_INSN(),
470                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
471                         BPF_EXIT_INSN(),
472                 },
473                 .fixup = {3},
474                 .errstr = "R0 invalid mem access",
475                 .result = REJECT,
476         },
477         {
478                 "jump test 1",
479                 .insns = {
480                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
481                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
482                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
483                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
484                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
485                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
486                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
487                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
488                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
489                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
490                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
491                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
492                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
493                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
494                         BPF_MOV64_IMM(BPF_REG_0, 0),
495                         BPF_EXIT_INSN(),
496                 },
497                 .result = ACCEPT,
498         },
499         {
500                 "jump test 2",
501                 .insns = {
502                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
503                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
504                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
505                         BPF_JMP_IMM(BPF_JA, 0, 0, 14),
506                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
507                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
508                         BPF_JMP_IMM(BPF_JA, 0, 0, 11),
509                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
510                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
511                         BPF_JMP_IMM(BPF_JA, 0, 0, 8),
512                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
513                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
514                         BPF_JMP_IMM(BPF_JA, 0, 0, 5),
515                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
516                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
517                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
518                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
519                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
520                         BPF_MOV64_IMM(BPF_REG_0, 0),
521                         BPF_EXIT_INSN(),
522                 },
523                 .result = ACCEPT,
524         },
525         {
526                 "jump test 3",
527                 .insns = {
528                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
529                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
530                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
531                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
532                         BPF_JMP_IMM(BPF_JA, 0, 0, 19),
533                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
534                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
535                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
536                         BPF_JMP_IMM(BPF_JA, 0, 0, 15),
537                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
538                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
539                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
540                         BPF_JMP_IMM(BPF_JA, 0, 0, 11),
541                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
542                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
543                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
544                         BPF_JMP_IMM(BPF_JA, 0, 0, 7),
545                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
546                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
547                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
548                         BPF_JMP_IMM(BPF_JA, 0, 0, 3),
549                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
550                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
551                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
552                         BPF_LD_MAP_FD(BPF_REG_1, 0),
553                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
554                         BPF_EXIT_INSN(),
555                 },
556                 .fixup = {24},
557                 .result = ACCEPT,
558         },
559         {
560                 "jump test 4",
561                 .insns = {
562                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
563                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
564                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
565                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
566                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
567                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
568                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
569                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
570                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
571                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
572                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
573                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
574                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
575                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
576                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
577                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
578                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
579                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
580                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
581                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
582                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
583                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
584                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
585                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
586                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
587                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
588                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
589                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
590                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
591                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
592                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
593                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
594                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
595                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
596                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
597                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
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_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
602                         BPF_MOV64_IMM(BPF_REG_0, 0),
603                         BPF_EXIT_INSN(),
604                 },
605                 .result = ACCEPT,
606         },
607         {
608                 "jump test 5",
609                 .insns = {
610                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
611                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
612                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
613                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
614                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
615                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
616                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
617                         BPF_MOV64_IMM(BPF_REG_0, 0),
618                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
619                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
620                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
621                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
622                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
623                         BPF_MOV64_IMM(BPF_REG_0, 0),
624                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
625                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
626                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
627                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
628                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
629                         BPF_MOV64_IMM(BPF_REG_0, 0),
630                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
631                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
632                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
633                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
634                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
635                         BPF_MOV64_IMM(BPF_REG_0, 0),
636                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
637                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
638                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
639                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
640                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
641                         BPF_MOV64_IMM(BPF_REG_0, 0),
642                         BPF_EXIT_INSN(),
643                 },
644                 .result = ACCEPT,
645         },
646         {
647                 "access skb fields ok",
648                 .insns = {
649                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
650                                     offsetof(struct __sk_buff, len)),
651                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
652                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
653                                     offsetof(struct __sk_buff, mark)),
654                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
655                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
656                                     offsetof(struct __sk_buff, pkt_type)),
657                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
658                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
659                                     offsetof(struct __sk_buff, queue_mapping)),
660                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
661                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
662                                     offsetof(struct __sk_buff, protocol)),
663                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
664                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
665                                     offsetof(struct __sk_buff, vlan_present)),
666                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
667                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
668                                     offsetof(struct __sk_buff, vlan_tci)),
669                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
670                         BPF_EXIT_INSN(),
671                 },
672                 .result = ACCEPT,
673         },
674         {
675                 "access skb fields bad1",
676                 .insns = {
677                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -4),
678                         BPF_EXIT_INSN(),
679                 },
680                 .errstr = "invalid bpf_context access",
681                 .result = REJECT,
682         },
683         {
684                 "access skb fields bad2",
685                 .insns = {
686                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 9),
687                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
688                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
689                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
690                         BPF_LD_MAP_FD(BPF_REG_1, 0),
691                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
692                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
693                         BPF_EXIT_INSN(),
694                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
695                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
696                                     offsetof(struct __sk_buff, pkt_type)),
697                         BPF_EXIT_INSN(),
698                 },
699                 .fixup = {4},
700                 .errstr = "different pointers",
701                 .result = REJECT,
702         },
703         {
704                 "access skb fields bad3",
705                 .insns = {
706                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
707                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
708                                     offsetof(struct __sk_buff, pkt_type)),
709                         BPF_EXIT_INSN(),
710                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
711                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
712                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
713                         BPF_LD_MAP_FD(BPF_REG_1, 0),
714                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
715                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
716                         BPF_EXIT_INSN(),
717                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
718                         BPF_JMP_IMM(BPF_JA, 0, 0, -12),
719                 },
720                 .fixup = {6},
721                 .errstr = "different pointers",
722                 .result = REJECT,
723         },
724         {
725                 "access skb fields bad4",
726                 .insns = {
727                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 3),
728                         BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
729                                     offsetof(struct __sk_buff, len)),
730                         BPF_MOV64_IMM(BPF_REG_0, 0),
731                         BPF_EXIT_INSN(),
732                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
733                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
734                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
735                         BPF_LD_MAP_FD(BPF_REG_1, 0),
736                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
737                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
738                         BPF_EXIT_INSN(),
739                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
740                         BPF_JMP_IMM(BPF_JA, 0, 0, -13),
741                 },
742                 .fixup = {7},
743                 .errstr = "different pointers",
744                 .result = REJECT,
745         },
746 };
747
748 static int probe_filter_length(struct bpf_insn *fp)
749 {
750         int len = 0;
751
752         for (len = MAX_INSNS - 1; len > 0; --len)
753                 if (fp[len].code != 0 || fp[len].imm != 0)
754                         break;
755
756         return len + 1;
757 }
758
759 static int create_map(void)
760 {
761         long long key, value = 0;
762         int map_fd;
763
764         map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1024);
765         if (map_fd < 0) {
766                 printf("failed to create map '%s'\n", strerror(errno));
767         }
768
769         return map_fd;
770 }
771
772 static int test(void)
773 {
774         int prog_fd, i, pass_cnt = 0, err_cnt = 0;
775
776         for (i = 0; i < ARRAY_SIZE(tests); i++) {
777                 struct bpf_insn *prog = tests[i].insns;
778                 int prog_len = probe_filter_length(prog);
779                 int *fixup = tests[i].fixup;
780                 int map_fd = -1;
781
782                 if (*fixup) {
783                         map_fd = create_map();
784
785                         do {
786                                 prog[*fixup].imm = map_fd;
787                                 fixup++;
788                         } while (*fixup);
789                 }
790                 printf("#%d %s ", i, tests[i].descr);
791
792                 prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog,
793                                         prog_len * sizeof(struct bpf_insn),
794                                         "GPL", 0);
795
796                 if (tests[i].result == ACCEPT) {
797                         if (prog_fd < 0) {
798                                 printf("FAIL\nfailed to load prog '%s'\n",
799                                        strerror(errno));
800                                 printf("%s", bpf_log_buf);
801                                 err_cnt++;
802                                 goto fail;
803                         }
804                 } else {
805                         if (prog_fd >= 0) {
806                                 printf("FAIL\nunexpected success to load\n");
807                                 printf("%s", bpf_log_buf);
808                                 err_cnt++;
809                                 goto fail;
810                         }
811                         if (strstr(bpf_log_buf, tests[i].errstr) == 0) {
812                                 printf("FAIL\nunexpected error message: %s",
813                                        bpf_log_buf);
814                                 err_cnt++;
815                                 goto fail;
816                         }
817                 }
818
819                 pass_cnt++;
820                 printf("OK\n");
821 fail:
822                 if (map_fd >= 0)
823                         close(map_fd);
824                 close(prog_fd);
825
826         }
827         printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
828
829         return 0;
830 }
831
832 int main(void)
833 {
834         return test();
835 }