]> git.karo-electronics.de Git - karo-tx-linux.git/blob - samples/bpf/test_verifier.c
sfc: replace spinlocks with bit ops for busy poll locking
[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 <stddef.h>
18 #include <stdbool.h>
19 #include <sys/resource.h>
20 #include "libbpf.h"
21
22 #define MAX_INSNS 512
23 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
24
25 #define MAX_FIXUPS 8
26
27 struct bpf_test {
28         const char *descr;
29         struct bpf_insn insns[MAX_INSNS];
30         int fixup[MAX_FIXUPS];
31         int prog_array_fixup[MAX_FIXUPS];
32         const char *errstr;
33         const char *errstr_unpriv;
34         enum {
35                 UNDEF,
36                 ACCEPT,
37                 REJECT
38         } result, result_unpriv;
39         enum bpf_prog_type prog_type;
40 };
41
42 static struct bpf_test tests[] = {
43         {
44                 "add+sub+mul",
45                 .insns = {
46                         BPF_MOV64_IMM(BPF_REG_1, 1),
47                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 2),
48                         BPF_MOV64_IMM(BPF_REG_2, 3),
49                         BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_2),
50                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1),
51                         BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 3),
52                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
53                         BPF_EXIT_INSN(),
54                 },
55                 .result = ACCEPT,
56         },
57         {
58                 "unreachable",
59                 .insns = {
60                         BPF_EXIT_INSN(),
61                         BPF_EXIT_INSN(),
62                 },
63                 .errstr = "unreachable",
64                 .result = REJECT,
65         },
66         {
67                 "unreachable2",
68                 .insns = {
69                         BPF_JMP_IMM(BPF_JA, 0, 0, 1),
70                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
71                         BPF_EXIT_INSN(),
72                 },
73                 .errstr = "unreachable",
74                 .result = REJECT,
75         },
76         {
77                 "out of range jump",
78                 .insns = {
79                         BPF_JMP_IMM(BPF_JA, 0, 0, 1),
80                         BPF_EXIT_INSN(),
81                 },
82                 .errstr = "jump out of range",
83                 .result = REJECT,
84         },
85         {
86                 "out of range jump2",
87                 .insns = {
88                         BPF_JMP_IMM(BPF_JA, 0, 0, -2),
89                         BPF_EXIT_INSN(),
90                 },
91                 .errstr = "jump out of range",
92                 .result = REJECT,
93         },
94         {
95                 "test1 ld_imm64",
96                 .insns = {
97                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
98                         BPF_LD_IMM64(BPF_REG_0, 0),
99                         BPF_LD_IMM64(BPF_REG_0, 0),
100                         BPF_LD_IMM64(BPF_REG_0, 1),
101                         BPF_LD_IMM64(BPF_REG_0, 1),
102                         BPF_MOV64_IMM(BPF_REG_0, 2),
103                         BPF_EXIT_INSN(),
104                 },
105                 .errstr = "invalid BPF_LD_IMM insn",
106                 .errstr_unpriv = "R1 pointer comparison",
107                 .result = REJECT,
108         },
109         {
110                 "test2 ld_imm64",
111                 .insns = {
112                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
113                         BPF_LD_IMM64(BPF_REG_0, 0),
114                         BPF_LD_IMM64(BPF_REG_0, 0),
115                         BPF_LD_IMM64(BPF_REG_0, 1),
116                         BPF_LD_IMM64(BPF_REG_0, 1),
117                         BPF_EXIT_INSN(),
118                 },
119                 .errstr = "invalid BPF_LD_IMM insn",
120                 .errstr_unpriv = "R1 pointer comparison",
121                 .result = REJECT,
122         },
123         {
124                 "test3 ld_imm64",
125                 .insns = {
126                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
127                         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
128                         BPF_LD_IMM64(BPF_REG_0, 0),
129                         BPF_LD_IMM64(BPF_REG_0, 0),
130                         BPF_LD_IMM64(BPF_REG_0, 1),
131                         BPF_LD_IMM64(BPF_REG_0, 1),
132                         BPF_EXIT_INSN(),
133                 },
134                 .errstr = "invalid bpf_ld_imm64 insn",
135                 .result = REJECT,
136         },
137         {
138                 "test4 ld_imm64",
139                 .insns = {
140                         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
141                         BPF_EXIT_INSN(),
142                 },
143                 .errstr = "invalid bpf_ld_imm64 insn",
144                 .result = REJECT,
145         },
146         {
147                 "test5 ld_imm64",
148                 .insns = {
149                         BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
150                 },
151                 .errstr = "invalid bpf_ld_imm64 insn",
152                 .result = REJECT,
153         },
154         {
155                 "no bpf_exit",
156                 .insns = {
157                         BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2),
158                 },
159                 .errstr = "jump out of range",
160                 .result = REJECT,
161         },
162         {
163                 "loop (back-edge)",
164                 .insns = {
165                         BPF_JMP_IMM(BPF_JA, 0, 0, -1),
166                         BPF_EXIT_INSN(),
167                 },
168                 .errstr = "back-edge",
169                 .result = REJECT,
170         },
171         {
172                 "loop2 (back-edge)",
173                 .insns = {
174                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
175                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
176                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
177                         BPF_JMP_IMM(BPF_JA, 0, 0, -4),
178                         BPF_EXIT_INSN(),
179                 },
180                 .errstr = "back-edge",
181                 .result = REJECT,
182         },
183         {
184                 "conditional loop",
185                 .insns = {
186                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
187                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
188                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
189                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3),
190                         BPF_EXIT_INSN(),
191                 },
192                 .errstr = "back-edge",
193                 .result = REJECT,
194         },
195         {
196                 "read uninitialized register",
197                 .insns = {
198                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
199                         BPF_EXIT_INSN(),
200                 },
201                 .errstr = "R2 !read_ok",
202                 .result = REJECT,
203         },
204         {
205                 "read invalid register",
206                 .insns = {
207                         BPF_MOV64_REG(BPF_REG_0, -1),
208                         BPF_EXIT_INSN(),
209                 },
210                 .errstr = "R15 is invalid",
211                 .result = REJECT,
212         },
213         {
214                 "program doesn't init R0 before exit",
215                 .insns = {
216                         BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
217                         BPF_EXIT_INSN(),
218                 },
219                 .errstr = "R0 !read_ok",
220                 .result = REJECT,
221         },
222         {
223                 "program doesn't init R0 before exit in all branches",
224                 .insns = {
225                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
226                         BPF_MOV64_IMM(BPF_REG_0, 1),
227                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
228                         BPF_EXIT_INSN(),
229                 },
230                 .errstr = "R0 !read_ok",
231                 .errstr_unpriv = "R1 pointer comparison",
232                 .result = REJECT,
233         },
234         {
235                 "stack out of bounds",
236                 .insns = {
237                         BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0),
238                         BPF_EXIT_INSN(),
239                 },
240                 .errstr = "invalid stack",
241                 .result = REJECT,
242         },
243         {
244                 "invalid call insn1",
245                 .insns = {
246                         BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0),
247                         BPF_EXIT_INSN(),
248                 },
249                 .errstr = "BPF_CALL uses reserved",
250                 .result = REJECT,
251         },
252         {
253                 "invalid call insn2",
254                 .insns = {
255                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0),
256                         BPF_EXIT_INSN(),
257                 },
258                 .errstr = "BPF_CALL uses reserved",
259                 .result = REJECT,
260         },
261         {
262                 "invalid function call",
263                 .insns = {
264                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567),
265                         BPF_EXIT_INSN(),
266                 },
267                 .errstr = "invalid func 1234567",
268                 .result = REJECT,
269         },
270         {
271                 "uninitialized stack1",
272                 .insns = {
273                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
274                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
275                         BPF_LD_MAP_FD(BPF_REG_1, 0),
276                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
277                         BPF_EXIT_INSN(),
278                 },
279                 .fixup = {2},
280                 .errstr = "invalid indirect read from stack",
281                 .result = REJECT,
282         },
283         {
284                 "uninitialized stack2",
285                 .insns = {
286                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
287                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8),
288                         BPF_EXIT_INSN(),
289                 },
290                 .errstr = "invalid read from stack",
291                 .result = REJECT,
292         },
293         {
294                 "check valid spill/fill",
295                 .insns = {
296                         /* spill R1(ctx) into stack */
297                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
298
299                         /* fill it back into R2 */
300                         BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
301
302                         /* should be able to access R0 = *(R2 + 8) */
303                         /* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
304                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
305                         BPF_EXIT_INSN(),
306                 },
307                 .errstr_unpriv = "R0 leaks addr",
308                 .result = ACCEPT,
309                 .result_unpriv = REJECT,
310         },
311         {
312                 "check corrupted spill/fill",
313                 .insns = {
314                         /* spill R1(ctx) into stack */
315                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
316
317                         /* mess up with R1 pointer on stack */
318                         BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
319
320                         /* fill back into R0 should fail */
321                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
322
323                         BPF_EXIT_INSN(),
324                 },
325                 .errstr_unpriv = "attempt to corrupt spilled",
326                 .errstr = "corrupted spill",
327                 .result = REJECT,
328         },
329         {
330                 "invalid src register in STX",
331                 .insns = {
332                         BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
333                         BPF_EXIT_INSN(),
334                 },
335                 .errstr = "R15 is invalid",
336                 .result = REJECT,
337         },
338         {
339                 "invalid dst register in STX",
340                 .insns = {
341                         BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
342                         BPF_EXIT_INSN(),
343                 },
344                 .errstr = "R14 is invalid",
345                 .result = REJECT,
346         },
347         {
348                 "invalid dst register in ST",
349                 .insns = {
350                         BPF_ST_MEM(BPF_B, 14, -1, -1),
351                         BPF_EXIT_INSN(),
352                 },
353                 .errstr = "R14 is invalid",
354                 .result = REJECT,
355         },
356         {
357                 "invalid src register in LDX",
358                 .insns = {
359                         BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
360                         BPF_EXIT_INSN(),
361                 },
362                 .errstr = "R12 is invalid",
363                 .result = REJECT,
364         },
365         {
366                 "invalid dst register in LDX",
367                 .insns = {
368                         BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
369                         BPF_EXIT_INSN(),
370                 },
371                 .errstr = "R11 is invalid",
372                 .result = REJECT,
373         },
374         {
375                 "junk insn",
376                 .insns = {
377                         BPF_RAW_INSN(0, 0, 0, 0, 0),
378                         BPF_EXIT_INSN(),
379                 },
380                 .errstr = "invalid BPF_LD_IMM",
381                 .result = REJECT,
382         },
383         {
384                 "junk insn2",
385                 .insns = {
386                         BPF_RAW_INSN(1, 0, 0, 0, 0),
387                         BPF_EXIT_INSN(),
388                 },
389                 .errstr = "BPF_LDX uses reserved fields",
390                 .result = REJECT,
391         },
392         {
393                 "junk insn3",
394                 .insns = {
395                         BPF_RAW_INSN(-1, 0, 0, 0, 0),
396                         BPF_EXIT_INSN(),
397                 },
398                 .errstr = "invalid BPF_ALU opcode f0",
399                 .result = REJECT,
400         },
401         {
402                 "junk insn4",
403                 .insns = {
404                         BPF_RAW_INSN(-1, -1, -1, -1, -1),
405                         BPF_EXIT_INSN(),
406                 },
407                 .errstr = "invalid BPF_ALU opcode f0",
408                 .result = REJECT,
409         },
410         {
411                 "junk insn5",
412                 .insns = {
413                         BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
414                         BPF_EXIT_INSN(),
415                 },
416                 .errstr = "BPF_ALU uses reserved fields",
417                 .result = REJECT,
418         },
419         {
420                 "misaligned read from stack",
421                 .insns = {
422                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
423                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
424                         BPF_EXIT_INSN(),
425                 },
426                 .errstr = "misaligned access",
427                 .result = REJECT,
428         },
429         {
430                 "invalid map_fd for function call",
431                 .insns = {
432                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
433                         BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
434                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
435                         BPF_LD_MAP_FD(BPF_REG_1, 0),
436                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
437                         BPF_EXIT_INSN(),
438                 },
439                 .errstr = "fd 0 is not pointing to valid bpf_map",
440                 .result = REJECT,
441         },
442         {
443                 "don't check return value before access",
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_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
451                         BPF_EXIT_INSN(),
452                 },
453                 .fixup = {3},
454                 .errstr = "R0 invalid mem access 'map_value_or_null'",
455                 .result = REJECT,
456         },
457         {
458                 "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, 1),
466                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
467                         BPF_EXIT_INSN(),
468                 },
469                 .fixup = {3},
470                 .errstr = "misaligned access",
471                 .result = REJECT,
472         },
473         {
474                 "sometimes access memory with incorrect alignment",
475                 .insns = {
476                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
477                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
478                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
479                         BPF_LD_MAP_FD(BPF_REG_1, 0),
480                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
481                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
482                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
483                         BPF_EXIT_INSN(),
484                         BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
485                         BPF_EXIT_INSN(),
486                 },
487                 .fixup = {3},
488                 .errstr = "R0 invalid mem access",
489                 .errstr_unpriv = "R0 leaks addr",
490                 .result = REJECT,
491         },
492         {
493                 "jump test 1",
494                 .insns = {
495                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
496                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
497                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
498                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
499                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
500                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
501                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
502                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
503                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
504                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
505                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
506                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
507                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
508                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
509                         BPF_MOV64_IMM(BPF_REG_0, 0),
510                         BPF_EXIT_INSN(),
511                 },
512                 .errstr_unpriv = "R1 pointer comparison",
513                 .result_unpriv = REJECT,
514                 .result = ACCEPT,
515         },
516         {
517                 "jump test 2",
518                 .insns = {
519                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
520                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
521                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
522                         BPF_JMP_IMM(BPF_JA, 0, 0, 14),
523                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
524                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
525                         BPF_JMP_IMM(BPF_JA, 0, 0, 11),
526                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
527                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
528                         BPF_JMP_IMM(BPF_JA, 0, 0, 8),
529                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
530                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
531                         BPF_JMP_IMM(BPF_JA, 0, 0, 5),
532                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
533                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
534                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
535                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
536                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
537                         BPF_MOV64_IMM(BPF_REG_0, 0),
538                         BPF_EXIT_INSN(),
539                 },
540                 .errstr_unpriv = "R1 pointer comparison",
541                 .result_unpriv = REJECT,
542                 .result = ACCEPT,
543         },
544         {
545                 "jump test 3",
546                 .insns = {
547                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
548                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
549                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
550                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
551                         BPF_JMP_IMM(BPF_JA, 0, 0, 19),
552                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
553                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
554                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
555                         BPF_JMP_IMM(BPF_JA, 0, 0, 15),
556                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
557                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
558                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
559                         BPF_JMP_IMM(BPF_JA, 0, 0, 11),
560                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
561                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
562                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
563                         BPF_JMP_IMM(BPF_JA, 0, 0, 7),
564                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
565                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
566                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
567                         BPF_JMP_IMM(BPF_JA, 0, 0, 3),
568                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
569                         BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
570                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
571                         BPF_LD_MAP_FD(BPF_REG_1, 0),
572                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
573                         BPF_EXIT_INSN(),
574                 },
575                 .fixup = {24},
576                 .errstr_unpriv = "R1 pointer comparison",
577                 .result_unpriv = REJECT,
578                 .result = ACCEPT,
579         },
580         {
581                 "jump test 4",
582                 .insns = {
583                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
584                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
585                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
586                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
587                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
588                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
589                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
590                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
591                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
592                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
593                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
594                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
595                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
596                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
597                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
598                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
599                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
600                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
601                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
602                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
603                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
604                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
605                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
606                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
607                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
608                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
609                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
610                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
611                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
612                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
613                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
614                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
615                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
616                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
617                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
618                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
619                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
620                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
621                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
622                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
623                         BPF_MOV64_IMM(BPF_REG_0, 0),
624                         BPF_EXIT_INSN(),
625                 },
626                 .errstr_unpriv = "R1 pointer comparison",
627                 .result_unpriv = REJECT,
628                 .result = ACCEPT,
629         },
630         {
631                 "jump test 5",
632                 .insns = {
633                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
634                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
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_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
642                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
643                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
644                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
645                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
646                         BPF_MOV64_IMM(BPF_REG_0, 0),
647                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
648                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
649                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
650                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
651                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
652                         BPF_MOV64_IMM(BPF_REG_0, 0),
653                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
654                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
655                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
656                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
657                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
658                         BPF_MOV64_IMM(BPF_REG_0, 0),
659                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
660                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
661                         BPF_JMP_IMM(BPF_JA, 0, 0, 2),
662                         BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
663                         BPF_JMP_IMM(BPF_JA, 0, 0, 0),
664                         BPF_MOV64_IMM(BPF_REG_0, 0),
665                         BPF_EXIT_INSN(),
666                 },
667                 .errstr_unpriv = "R1 pointer comparison",
668                 .result_unpriv = REJECT,
669                 .result = ACCEPT,
670         },
671         {
672                 "access skb fields ok",
673                 .insns = {
674                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
675                                     offsetof(struct __sk_buff, len)),
676                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
677                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
678                                     offsetof(struct __sk_buff, mark)),
679                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
680                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
681                                     offsetof(struct __sk_buff, pkt_type)),
682                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
683                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
684                                     offsetof(struct __sk_buff, queue_mapping)),
685                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
686                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
687                                     offsetof(struct __sk_buff, protocol)),
688                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
689                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
690                                     offsetof(struct __sk_buff, vlan_present)),
691                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
692                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
693                                     offsetof(struct __sk_buff, vlan_tci)),
694                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
695                         BPF_EXIT_INSN(),
696                 },
697                 .result = ACCEPT,
698         },
699         {
700                 "access skb fields bad1",
701                 .insns = {
702                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -4),
703                         BPF_EXIT_INSN(),
704                 },
705                 .errstr = "invalid bpf_context access",
706                 .result = REJECT,
707         },
708         {
709                 "access skb fields bad2",
710                 .insns = {
711                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 9),
712                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
713                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
714                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
715                         BPF_LD_MAP_FD(BPF_REG_1, 0),
716                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
717                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
718                         BPF_EXIT_INSN(),
719                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
720                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
721                                     offsetof(struct __sk_buff, pkt_type)),
722                         BPF_EXIT_INSN(),
723                 },
724                 .fixup = {4},
725                 .errstr = "different pointers",
726                 .errstr_unpriv = "R1 pointer comparison",
727                 .result = REJECT,
728         },
729         {
730                 "access skb fields bad3",
731                 .insns = {
732                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
733                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
734                                     offsetof(struct __sk_buff, pkt_type)),
735                         BPF_EXIT_INSN(),
736                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
737                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
738                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
739                         BPF_LD_MAP_FD(BPF_REG_1, 0),
740                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
741                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
742                         BPF_EXIT_INSN(),
743                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
744                         BPF_JMP_IMM(BPF_JA, 0, 0, -12),
745                 },
746                 .fixup = {6},
747                 .errstr = "different pointers",
748                 .errstr_unpriv = "R1 pointer comparison",
749                 .result = REJECT,
750         },
751         {
752                 "access skb fields bad4",
753                 .insns = {
754                         BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 3),
755                         BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
756                                     offsetof(struct __sk_buff, len)),
757                         BPF_MOV64_IMM(BPF_REG_0, 0),
758                         BPF_EXIT_INSN(),
759                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
760                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
761                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
762                         BPF_LD_MAP_FD(BPF_REG_1, 0),
763                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
764                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
765                         BPF_EXIT_INSN(),
766                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
767                         BPF_JMP_IMM(BPF_JA, 0, 0, -13),
768                 },
769                 .fixup = {7},
770                 .errstr = "different pointers",
771                 .errstr_unpriv = "R1 pointer comparison",
772                 .result = REJECT,
773         },
774         {
775                 "check skb->mark is not writeable by sockets",
776                 .insns = {
777                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
778                                     offsetof(struct __sk_buff, mark)),
779                         BPF_EXIT_INSN(),
780                 },
781                 .errstr = "invalid bpf_context access",
782                 .errstr_unpriv = "R1 leaks addr",
783                 .result = REJECT,
784         },
785         {
786                 "check skb->tc_index is not writeable by sockets",
787                 .insns = {
788                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
789                                     offsetof(struct __sk_buff, tc_index)),
790                         BPF_EXIT_INSN(),
791                 },
792                 .errstr = "invalid bpf_context access",
793                 .errstr_unpriv = "R1 leaks addr",
794                 .result = REJECT,
795         },
796         {
797                 "check non-u32 access to cb",
798                 .insns = {
799                         BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_1,
800                                     offsetof(struct __sk_buff, cb[0])),
801                         BPF_EXIT_INSN(),
802                 },
803                 .errstr = "invalid bpf_context access",
804                 .errstr_unpriv = "R1 leaks addr",
805                 .result = REJECT,
806         },
807         {
808                 "check out of range skb->cb access",
809                 .insns = {
810                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
811                                     offsetof(struct __sk_buff, cb[0]) + 256),
812                         BPF_EXIT_INSN(),
813                 },
814                 .errstr = "invalid bpf_context access",
815                 .errstr_unpriv = "",
816                 .result = REJECT,
817                 .prog_type = BPF_PROG_TYPE_SCHED_ACT,
818         },
819         {
820                 "write skb fields from socket prog",
821                 .insns = {
822                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
823                                     offsetof(struct __sk_buff, cb[4])),
824                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
825                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
826                                     offsetof(struct __sk_buff, mark)),
827                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
828                                     offsetof(struct __sk_buff, tc_index)),
829                         BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
830                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
831                                     offsetof(struct __sk_buff, cb[0])),
832                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
833                                     offsetof(struct __sk_buff, cb[2])),
834                         BPF_EXIT_INSN(),
835                 },
836                 .result = ACCEPT,
837                 .errstr_unpriv = "R1 leaks addr",
838                 .result_unpriv = REJECT,
839         },
840         {
841                 "write skb fields from tc_cls_act prog",
842                 .insns = {
843                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
844                                     offsetof(struct __sk_buff, cb[0])),
845                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
846                                     offsetof(struct __sk_buff, mark)),
847                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
848                                     offsetof(struct __sk_buff, tc_index)),
849                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
850                                     offsetof(struct __sk_buff, tc_index)),
851                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
852                                     offsetof(struct __sk_buff, cb[3])),
853                         BPF_EXIT_INSN(),
854                 },
855                 .errstr_unpriv = "",
856                 .result_unpriv = REJECT,
857                 .result = ACCEPT,
858                 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
859         },
860         {
861                 "PTR_TO_STACK store/load",
862                 .insns = {
863                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
864                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10),
865                         BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c),
866                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2),
867                         BPF_EXIT_INSN(),
868                 },
869                 .result = ACCEPT,
870         },
871         {
872                 "PTR_TO_STACK store/load - bad alignment on off",
873                 .insns = {
874                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
875                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
876                         BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c),
877                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2),
878                         BPF_EXIT_INSN(),
879                 },
880                 .result = REJECT,
881                 .errstr = "misaligned access off -6 size 8",
882         },
883         {
884                 "PTR_TO_STACK store/load - bad alignment on reg",
885                 .insns = {
886                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
887                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10),
888                         BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
889                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
890                         BPF_EXIT_INSN(),
891                 },
892                 .result = REJECT,
893                 .errstr = "misaligned access off -2 size 8",
894         },
895         {
896                 "PTR_TO_STACK store/load - out of bounds low",
897                 .insns = {
898                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
899                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -80000),
900                         BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
901                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
902                         BPF_EXIT_INSN(),
903                 },
904                 .result = REJECT,
905                 .errstr = "invalid stack off=-79992 size=8",
906         },
907         {
908                 "PTR_TO_STACK store/load - out of bounds high",
909                 .insns = {
910                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
911                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
912                         BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
913                         BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
914                         BPF_EXIT_INSN(),
915                 },
916                 .result = REJECT,
917                 .errstr = "invalid stack off=0 size=8",
918         },
919         {
920                 "unpriv: return pointer",
921                 .insns = {
922                         BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
923                         BPF_EXIT_INSN(),
924                 },
925                 .result = ACCEPT,
926                 .result_unpriv = REJECT,
927                 .errstr_unpriv = "R0 leaks addr",
928         },
929         {
930                 "unpriv: add const to pointer",
931                 .insns = {
932                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
933                         BPF_MOV64_IMM(BPF_REG_0, 0),
934                         BPF_EXIT_INSN(),
935                 },
936                 .result = ACCEPT,
937                 .result_unpriv = REJECT,
938                 .errstr_unpriv = "R1 pointer arithmetic",
939         },
940         {
941                 "unpriv: add pointer to pointer",
942                 .insns = {
943                         BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_10),
944                         BPF_MOV64_IMM(BPF_REG_0, 0),
945                         BPF_EXIT_INSN(),
946                 },
947                 .result = ACCEPT,
948                 .result_unpriv = REJECT,
949                 .errstr_unpriv = "R1 pointer arithmetic",
950         },
951         {
952                 "unpriv: neg pointer",
953                 .insns = {
954                         BPF_ALU64_IMM(BPF_NEG, BPF_REG_1, 0),
955                         BPF_MOV64_IMM(BPF_REG_0, 0),
956                         BPF_EXIT_INSN(),
957                 },
958                 .result = ACCEPT,
959                 .result_unpriv = REJECT,
960                 .errstr_unpriv = "R1 pointer arithmetic",
961         },
962         {
963                 "unpriv: cmp pointer with const",
964                 .insns = {
965                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0),
966                         BPF_MOV64_IMM(BPF_REG_0, 0),
967                         BPF_EXIT_INSN(),
968                 },
969                 .result = ACCEPT,
970                 .result_unpriv = REJECT,
971                 .errstr_unpriv = "R1 pointer comparison",
972         },
973         {
974                 "unpriv: cmp pointer with pointer",
975                 .insns = {
976                         BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
977                         BPF_MOV64_IMM(BPF_REG_0, 0),
978                         BPF_EXIT_INSN(),
979                 },
980                 .result = ACCEPT,
981                 .result_unpriv = REJECT,
982                 .errstr_unpriv = "R10 pointer comparison",
983         },
984         {
985                 "unpriv: check that printk is disallowed",
986                 .insns = {
987                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
988                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
989                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
990                         BPF_MOV64_IMM(BPF_REG_2, 8),
991                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
992                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_trace_printk),
993                         BPF_MOV64_IMM(BPF_REG_0, 0),
994                         BPF_EXIT_INSN(),
995                 },
996                 .errstr_unpriv = "unknown func 6",
997                 .result_unpriv = REJECT,
998                 .result = ACCEPT,
999         },
1000         {
1001                 "unpriv: pass pointer to helper function",
1002                 .insns = {
1003                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
1004                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
1005                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
1006                         BPF_LD_MAP_FD(BPF_REG_1, 0),
1007                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
1008                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
1009                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
1010                         BPF_MOV64_IMM(BPF_REG_0, 0),
1011                         BPF_EXIT_INSN(),
1012                 },
1013                 .fixup = {3},
1014                 .errstr_unpriv = "R4 leaks addr",
1015                 .result_unpriv = REJECT,
1016                 .result = ACCEPT,
1017         },
1018         {
1019                 "unpriv: indirectly pass pointer on stack to helper function",
1020                 .insns = {
1021                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
1022                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
1023                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
1024                         BPF_LD_MAP_FD(BPF_REG_1, 0),
1025                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
1026                         BPF_MOV64_IMM(BPF_REG_0, 0),
1027                         BPF_EXIT_INSN(),
1028                 },
1029                 .fixup = {3},
1030                 .errstr = "invalid indirect read from stack off -8+0 size 8",
1031                 .result = REJECT,
1032         },
1033         {
1034                 "unpriv: mangle pointer on stack 1",
1035                 .insns = {
1036                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
1037                         BPF_ST_MEM(BPF_W, BPF_REG_10, -8, 0),
1038                         BPF_MOV64_IMM(BPF_REG_0, 0),
1039                         BPF_EXIT_INSN(),
1040                 },
1041                 .errstr_unpriv = "attempt to corrupt spilled",
1042                 .result_unpriv = REJECT,
1043                 .result = ACCEPT,
1044         },
1045         {
1046                 "unpriv: mangle pointer on stack 2",
1047                 .insns = {
1048                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
1049                         BPF_ST_MEM(BPF_B, BPF_REG_10, -1, 0),
1050                         BPF_MOV64_IMM(BPF_REG_0, 0),
1051                         BPF_EXIT_INSN(),
1052                 },
1053                 .errstr_unpriv = "attempt to corrupt spilled",
1054                 .result_unpriv = REJECT,
1055                 .result = ACCEPT,
1056         },
1057         {
1058                 "unpriv: read pointer from stack in small chunks",
1059                 .insns = {
1060                         BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
1061                         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8),
1062                         BPF_MOV64_IMM(BPF_REG_0, 0),
1063                         BPF_EXIT_INSN(),
1064                 },
1065                 .errstr = "invalid size",
1066                 .result = REJECT,
1067         },
1068         {
1069                 "unpriv: write pointer into ctx",
1070                 .insns = {
1071                         BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, 0),
1072                         BPF_MOV64_IMM(BPF_REG_0, 0),
1073                         BPF_EXIT_INSN(),
1074                 },
1075                 .errstr_unpriv = "R1 leaks addr",
1076                 .result_unpriv = REJECT,
1077                 .errstr = "invalid bpf_context access",
1078                 .result = REJECT,
1079         },
1080         {
1081                 "unpriv: write pointer into map elem value",
1082                 .insns = {
1083                         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
1084                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
1085                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
1086                         BPF_LD_MAP_FD(BPF_REG_1, 0),
1087                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
1088                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
1089                         BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
1090                         BPF_EXIT_INSN(),
1091                 },
1092                 .fixup = {3},
1093                 .errstr_unpriv = "R0 leaks addr",
1094                 .result_unpriv = REJECT,
1095                 .result = ACCEPT,
1096         },
1097         {
1098                 "unpriv: partial copy of pointer",
1099                 .insns = {
1100                         BPF_MOV32_REG(BPF_REG_1, BPF_REG_10),
1101                         BPF_MOV64_IMM(BPF_REG_0, 0),
1102                         BPF_EXIT_INSN(),
1103                 },
1104                 .errstr_unpriv = "R10 partial copy",
1105                 .result_unpriv = REJECT,
1106                 .result = ACCEPT,
1107         },
1108         {
1109                 "unpriv: pass pointer to tail_call",
1110                 .insns = {
1111                         BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
1112                         BPF_LD_MAP_FD(BPF_REG_2, 0),
1113                         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
1114                         BPF_MOV64_IMM(BPF_REG_0, 0),
1115                         BPF_EXIT_INSN(),
1116                 },
1117                 .prog_array_fixup = {1},
1118                 .errstr_unpriv = "R3 leaks addr into helper",
1119                 .result_unpriv = REJECT,
1120                 .result = ACCEPT,
1121         },
1122         {
1123                 "unpriv: cmp map pointer with zero",
1124                 .insns = {
1125                         BPF_MOV64_IMM(BPF_REG_1, 0),
1126                         BPF_LD_MAP_FD(BPF_REG_1, 0),
1127                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0),
1128                         BPF_MOV64_IMM(BPF_REG_0, 0),
1129                         BPF_EXIT_INSN(),
1130                 },
1131                 .fixup = {1},
1132                 .errstr_unpriv = "R1 pointer comparison",
1133                 .result_unpriv = REJECT,
1134                 .result = ACCEPT,
1135         },
1136         {
1137                 "unpriv: write into frame pointer",
1138                 .insns = {
1139                         BPF_MOV64_REG(BPF_REG_10, BPF_REG_1),
1140                         BPF_MOV64_IMM(BPF_REG_0, 0),
1141                         BPF_EXIT_INSN(),
1142                 },
1143                 .errstr = "frame pointer is read only",
1144                 .result = REJECT,
1145         },
1146         {
1147                 "unpriv: cmp of frame pointer",
1148                 .insns = {
1149                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_10, 0, 0),
1150                         BPF_MOV64_IMM(BPF_REG_0, 0),
1151                         BPF_EXIT_INSN(),
1152                 },
1153                 .errstr_unpriv = "R10 pointer comparison",
1154                 .result_unpriv = REJECT,
1155                 .result = ACCEPT,
1156         },
1157         {
1158                 "unpriv: cmp of stack pointer",
1159                 .insns = {
1160                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
1161                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
1162                         BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 0),
1163                         BPF_MOV64_IMM(BPF_REG_0, 0),
1164                         BPF_EXIT_INSN(),
1165                 },
1166                 .errstr_unpriv = "R2 pointer comparison",
1167                 .result_unpriv = REJECT,
1168                 .result = ACCEPT,
1169         },
1170         {
1171                 "unpriv: obfuscate stack pointer",
1172                 .insns = {
1173                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
1174                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
1175                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
1176                         BPF_MOV64_IMM(BPF_REG_0, 0),
1177                         BPF_EXIT_INSN(),
1178                 },
1179                 .errstr_unpriv = "R2 pointer arithmetic",
1180                 .result_unpriv = REJECT,
1181                 .result = ACCEPT,
1182         },
1183 };
1184
1185 static int probe_filter_length(struct bpf_insn *fp)
1186 {
1187         int len = 0;
1188
1189         for (len = MAX_INSNS - 1; len > 0; --len)
1190                 if (fp[len].code != 0 || fp[len].imm != 0)
1191                         break;
1192
1193         return len + 1;
1194 }
1195
1196 static int create_map(void)
1197 {
1198         int map_fd;
1199
1200         map_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
1201                                 sizeof(long long), sizeof(long long), 1024);
1202         if (map_fd < 0)
1203                 printf("failed to create map '%s'\n", strerror(errno));
1204
1205         return map_fd;
1206 }
1207
1208 static int create_prog_array(void)
1209 {
1210         int map_fd;
1211
1212         map_fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY,
1213                                 sizeof(int), sizeof(int), 4);
1214         if (map_fd < 0)
1215                 printf("failed to create prog_array '%s'\n", strerror(errno));
1216
1217         return map_fd;
1218 }
1219
1220 static int test(void)
1221 {
1222         int prog_fd, i, pass_cnt = 0, err_cnt = 0;
1223         bool unpriv = geteuid() != 0;
1224
1225         for (i = 0; i < ARRAY_SIZE(tests); i++) {
1226                 struct bpf_insn *prog = tests[i].insns;
1227                 int prog_type = tests[i].prog_type;
1228                 int prog_len = probe_filter_length(prog);
1229                 int *fixup = tests[i].fixup;
1230                 int *prog_array_fixup = tests[i].prog_array_fixup;
1231                 int expected_result;
1232                 const char *expected_errstr;
1233                 int map_fd = -1, prog_array_fd = -1;
1234
1235                 if (*fixup) {
1236                         map_fd = create_map();
1237
1238                         do {
1239                                 prog[*fixup].imm = map_fd;
1240                                 fixup++;
1241                         } while (*fixup);
1242                 }
1243                 if (*prog_array_fixup) {
1244                         prog_array_fd = create_prog_array();
1245
1246                         do {
1247                                 prog[*prog_array_fixup].imm = prog_array_fd;
1248                                 prog_array_fixup++;
1249                         } while (*prog_array_fixup);
1250                 }
1251                 printf("#%d %s ", i, tests[i].descr);
1252
1253                 prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
1254                                         prog, prog_len * sizeof(struct bpf_insn),
1255                                         "GPL", 0);
1256
1257                 if (unpriv && tests[i].result_unpriv != UNDEF)
1258                         expected_result = tests[i].result_unpriv;
1259                 else
1260                         expected_result = tests[i].result;
1261
1262                 if (unpriv && tests[i].errstr_unpriv)
1263                         expected_errstr = tests[i].errstr_unpriv;
1264                 else
1265                         expected_errstr = tests[i].errstr;
1266
1267                 if (expected_result == ACCEPT) {
1268                         if (prog_fd < 0) {
1269                                 printf("FAIL\nfailed to load prog '%s'\n",
1270                                        strerror(errno));
1271                                 printf("%s", bpf_log_buf);
1272                                 err_cnt++;
1273                                 goto fail;
1274                         }
1275                 } else {
1276                         if (prog_fd >= 0) {
1277                                 printf("FAIL\nunexpected success to load\n");
1278                                 printf("%s", bpf_log_buf);
1279                                 err_cnt++;
1280                                 goto fail;
1281                         }
1282                         if (strstr(bpf_log_buf, expected_errstr) == 0) {
1283                                 printf("FAIL\nunexpected error message: %s",
1284                                        bpf_log_buf);
1285                                 err_cnt++;
1286                                 goto fail;
1287                         }
1288                 }
1289
1290                 pass_cnt++;
1291                 printf("OK\n");
1292 fail:
1293                 if (map_fd >= 0)
1294                         close(map_fd);
1295                 if (prog_array_fd >= 0)
1296                         close(prog_array_fd);
1297                 close(prog_fd);
1298
1299         }
1300         printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
1301
1302         return 0;
1303 }
1304
1305 int main(void)
1306 {
1307         struct rlimit r = {1 << 20, 1 << 20};
1308
1309         setrlimit(RLIMIT_MEMLOCK, &r);
1310         return test();
1311 }