1#include <asm/types.h>
2#include <linux/types.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <errno.h>
8#include <string.h>
9#include <stddef.h>
10#include <stdbool.h>
11
12#include <linux/unistd.h>
13#include <linux/filter.h>
14#include <linux/bpf_perf_event.h>
15#include <linux/bpf.h>
16
17#include <bpf/bpf.h>
18
19#include "../../../include/linux/filter.h"
20#include "bpf_rlimit.h"
21#include "bpf_util.h"
22
23#define MAX_INSNS 512
24#define MAX_MATCHES 16
25
26struct bpf_reg_match {
27 unsigned int line;
28 const char *match;
29};
30
31struct bpf_align_test {
32 const char *descr;
33 struct bpf_insn insns[MAX_INSNS];
34 enum {
35 UNDEF,
36 ACCEPT,
37 REJECT
38 } result;
39 enum bpf_prog_type prog_type;
40
41 struct bpf_reg_match matches[MAX_MATCHES];
42};
43
44static struct bpf_align_test tests[] = {
45
46
47
48 {
49 .descr = "mov",
50 .insns = {
51 BPF_MOV64_IMM(BPF_REG_3, 2),
52 BPF_MOV64_IMM(BPF_REG_3, 4),
53 BPF_MOV64_IMM(BPF_REG_3, 8),
54 BPF_MOV64_IMM(BPF_REG_3, 16),
55 BPF_MOV64_IMM(BPF_REG_3, 32),
56 BPF_MOV64_IMM(BPF_REG_0, 0),
57 BPF_EXIT_INSN(),
58 },
59 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
60 .matches = {
61 {1, "R1=ctx(id=0,off=0,imm=0)"},
62 {1, "R10=fp0"},
63 {1, "R3_w=inv2"},
64 {2, "R3_w=inv4"},
65 {3, "R3_w=inv8"},
66 {4, "R3_w=inv16"},
67 {5, "R3_w=inv32"},
68 },
69 },
70 {
71 .descr = "shift",
72 .insns = {
73 BPF_MOV64_IMM(BPF_REG_3, 1),
74 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
75 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
76 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
77 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
78 BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4),
79 BPF_MOV64_IMM(BPF_REG_4, 32),
80 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
81 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
82 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
83 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
84 BPF_MOV64_IMM(BPF_REG_0, 0),
85 BPF_EXIT_INSN(),
86 },
87 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
88 .matches = {
89 {1, "R1=ctx(id=0,off=0,imm=0)"},
90 {1, "R10=fp0"},
91 {1, "R3_w=inv1"},
92 {2, "R3_w=inv2"},
93 {3, "R3_w=inv4"},
94 {4, "R3_w=inv8"},
95 {5, "R3_w=inv16"},
96 {6, "R3_w=inv1"},
97 {7, "R4_w=inv32"},
98 {8, "R4_w=inv16"},
99 {9, "R4_w=inv8"},
100 {10, "R4_w=inv4"},
101 {11, "R4_w=inv2"},
102 },
103 },
104 {
105 .descr = "addsub",
106 .insns = {
107 BPF_MOV64_IMM(BPF_REG_3, 4),
108 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4),
109 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2),
110 BPF_MOV64_IMM(BPF_REG_4, 8),
111 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
112 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
113 BPF_MOV64_IMM(BPF_REG_0, 0),
114 BPF_EXIT_INSN(),
115 },
116 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
117 .matches = {
118 {1, "R1=ctx(id=0,off=0,imm=0)"},
119 {1, "R10=fp0"},
120 {1, "R3_w=inv4"},
121 {2, "R3_w=inv8"},
122 {3, "R3_w=inv10"},
123 {4, "R4_w=inv8"},
124 {5, "R4_w=inv12"},
125 {6, "R4_w=inv14"},
126 },
127 },
128 {
129 .descr = "mul",
130 .insns = {
131 BPF_MOV64_IMM(BPF_REG_3, 7),
132 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1),
133 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2),
134 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4),
135 BPF_MOV64_IMM(BPF_REG_0, 0),
136 BPF_EXIT_INSN(),
137 },
138 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
139 .matches = {
140 {1, "R1=ctx(id=0,off=0,imm=0)"},
141 {1, "R10=fp0"},
142 {1, "R3_w=inv7"},
143 {2, "R3_w=inv7"},
144 {3, "R3_w=inv14"},
145 {4, "R3_w=inv56"},
146 },
147 },
148
149
150#define PREP_PKT_POINTERS \
151 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
152 offsetof(struct __sk_buff, data)), \
153 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \
154 offsetof(struct __sk_buff, data_end))
155
156#define LOAD_UNKNOWN(DST_REG) \
157 PREP_PKT_POINTERS, \
158 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \
159 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \
160 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \
161 BPF_EXIT_INSN(), \
162 BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0)
163
164 {
165 .descr = "unknown shift",
166 .insns = {
167 LOAD_UNKNOWN(BPF_REG_3),
168 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
169 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
170 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
171 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
172 LOAD_UNKNOWN(BPF_REG_4),
173 BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5),
174 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
175 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
176 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
177 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
178 BPF_MOV64_IMM(BPF_REG_0, 0),
179 BPF_EXIT_INSN(),
180 },
181 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
182 .matches = {
183 {7, "R0=pkt(id=0,off=8,r=8,imm=0)"},
184 {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
185 {8, "R3_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
186 {9, "R3_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
187 {10, "R3_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
188 {11, "R3_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
189 {18, "R3=pkt_end(id=0,off=0,imm=0)"},
190 {18, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
191 {19, "R4_w=inv(id=0,umax_value=8160,var_off=(0x0; 0x1fe0))"},
192 {20, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
193 {21, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
194 {22, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
195 {23, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
196 },
197 },
198 {
199 .descr = "unknown mul",
200 .insns = {
201 LOAD_UNKNOWN(BPF_REG_3),
202 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
203 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1),
204 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
205 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
206 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
207 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4),
208 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
209 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8),
210 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
211 BPF_MOV64_IMM(BPF_REG_0, 0),
212 BPF_EXIT_INSN(),
213 },
214 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
215 .matches = {
216 {7, "R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
217 {8, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
218 {9, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
219 {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
220 {11, "R4_w=inv(id=0,umax_value=510,var_off=(0x0; 0x1fe))"},
221 {12, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
222 {13, "R4_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
223 {14, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
224 {15, "R4_w=inv(id=0,umax_value=2040,var_off=(0x0; 0x7f8))"},
225 {16, "R4_w=inv(id=0,umax_value=4080,var_off=(0x0; 0xff0))"},
226 },
227 },
228 {
229 .descr = "packet const offset",
230 .insns = {
231 PREP_PKT_POINTERS,
232 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
233
234 BPF_MOV64_IMM(BPF_REG_0, 0),
235
236
237 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
238 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
239 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
240 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
241 BPF_EXIT_INSN(),
242
243 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0),
244 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1),
245 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2),
246 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3),
247 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0),
248 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2),
249 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
250
251 BPF_MOV64_IMM(BPF_REG_0, 0),
252 BPF_EXIT_INSN(),
253 },
254 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
255 .matches = {
256 {4, "R5_w=pkt(id=0,off=0,r=0,imm=0)"},
257 {5, "R5_w=pkt(id=0,off=14,r=0,imm=0)"},
258 {6, "R4_w=pkt(id=0,off=14,r=0,imm=0)"},
259 {10, "R2=pkt(id=0,off=0,r=18,imm=0)"},
260 {10, "R5=pkt(id=0,off=14,r=18,imm=0)"},
261 {10, "R4_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff))"},
262 {14, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
263 {15, "R4_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff))"},
264 },
265 },
266 {
267 .descr = "packet variable offset",
268 .insns = {
269 LOAD_UNKNOWN(BPF_REG_6),
270 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
271
272
273
274
275 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
276 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
277 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
278 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
279 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
280 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
281 BPF_EXIT_INSN(),
282 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
283
284
285
286
287 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
288 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
289 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
290 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
291 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
292 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
293 BPF_EXIT_INSN(),
294 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
295
296
297
298
299 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
300 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
301 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
302 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4),
303 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
304 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
305 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
306 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
307 BPF_EXIT_INSN(),
308 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
309
310 BPF_MOV64_IMM(BPF_REG_0, 0),
311 BPF_EXIT_INSN(),
312 },
313 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
314 .matches = {
315
316
317
318 {8, "R2=pkt(id=0,off=0,r=8,imm=0)"},
319 {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
320
321
322
323 {11, "R5_w=pkt(id=1,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
324
325
326
327
328
329
330 {15, "R4=pkt(id=1,off=18,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
331 {15, "R5=pkt(id=1,off=14,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
332
333
334
335 {18, "R5_w=pkt(id=2,off=0,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
336
337
338
339 {19, "R5_w=pkt(id=2,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
340
341
342
343
344
345
346 {23, "R4=pkt(id=2,off=18,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
347 {23, "R5=pkt(id=2,off=14,r=18,umax_value=1020,var_off=(0x0; 0x3fc))"},
348
349
350
351 {26, "R5_w=pkt(id=0,off=14,r=8"},
352
353
354
355 {27, "R5_w=pkt(id=3,off=14,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
356
357 {28, "R5_w=pkt(id=3,off=18,r=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
358
359
360
361
362 {29, "R5_w=pkt(id=4,off=18,r=0,umax_value=2040,var_off=(0x0; 0x7fc))"},
363
364
365
366
367
368
369 {33, "R4=pkt(id=4,off=22,r=22,umax_value=2040,var_off=(0x0; 0x7fc))"},
370 {33, "R5=pkt(id=4,off=18,r=22,umax_value=2040,var_off=(0x0; 0x7fc))"},
371 },
372 },
373 {
374 .descr = "packet variable offset 2",
375 .insns = {
376
377 LOAD_UNKNOWN(BPF_REG_6),
378 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
379 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
380
381 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
382 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
383
384 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
385 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
386 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
387 BPF_EXIT_INSN(),
388 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
389
390 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xff),
391 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
392
393 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
394
395 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
396 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
397 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
398 BPF_EXIT_INSN(),
399 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
400 BPF_MOV64_IMM(BPF_REG_0, 0),
401 BPF_EXIT_INSN(),
402 },
403 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
404 .matches = {
405
406
407
408 {8, "R2=pkt(id=0,off=0,r=8,imm=0)"},
409 {8, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
410
411 {9, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
412
413 {11, "R5_w=pkt(id=1,off=0,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
414 {13, "R4=pkt(id=1,off=4,r=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
415
416
417
418
419
420
421 {15, "R5=pkt(id=1,off=0,r=4,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
422
423
424
425 {18, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
426
427
428
429 {19, "R5_w=pkt(id=2,off=0,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
430 {21, "R4=pkt(id=2,off=4,r=0,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
431
432
433
434
435
436
437 {23, "R5=pkt(id=2,off=0,r=4,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
438 },
439 },
440 {
441 .descr = "dubious pointer arithmetic",
442 .insns = {
443 PREP_PKT_POINTERS,
444 BPF_MOV64_IMM(BPF_REG_0, 0),
445
446 BPF_MOV64_REG(BPF_REG_5, BPF_REG_3),
447 BPF_ALU64_REG(BPF_SUB, BPF_REG_5, BPF_REG_2),
448 BPF_ALU64_IMM(BPF_LSH, BPF_REG_5, 2),
449
450
451
452 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
453
454 BPF_JMP_IMM(BPF_JSGE, BPF_REG_5, 0, 1),
455 BPF_EXIT_INSN(),
456
457 BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
458 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
459
460 BPF_MOV64_REG(BPF_REG_4, BPF_REG_6),
461 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
462 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
463 BPF_EXIT_INSN(),
464 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_6, 0),
465 BPF_EXIT_INSN(),
466 },
467 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
468 .result = REJECT,
469 .matches = {
470 {4, "R5_w=pkt_end(id=0,off=0,imm=0)"},
471
472 {6, "R5_w=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc))"},
473
474
475
476 {7, "R5=inv(id=0,var_off=(0x2; 0xfffffffffffffffc))"},
477
478 {9, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
479
480 {11, "R6_w=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
481 {13, "R4=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
482
483
484
485
486
487
488
489 {15, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
490 }
491 },
492 {
493 .descr = "variable subtraction",
494 .insns = {
495
496 LOAD_UNKNOWN(BPF_REG_6),
497 BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
498 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
499 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
500
501
502
503 BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
504 BPF_ALU64_REG(BPF_SUB, BPF_REG_6, BPF_REG_7),
505
506 BPF_JMP_IMM(BPF_JSGE, BPF_REG_6, 0, 1),
507 BPF_EXIT_INSN(),
508
509 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
510 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
511
512 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
513 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
514 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
515 BPF_EXIT_INSN(),
516 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
517 BPF_EXIT_INSN(),
518 },
519 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
520 .matches = {
521
522
523
524 {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
525 {9, "R6_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
526
527 {10, "R6_w=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
528
529 {11, "R7_w=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
530
531 {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,var_off=(0x2; 0xfffffffffffffffc))"},
532
533 {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
534
535
536
537
538
539
540 {20, "R5=pkt(id=1,off=0,r=4,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
541 },
542 },
543 {
544 .descr = "pointer variable subtraction",
545 .insns = {
546
547
548
549 LOAD_UNKNOWN(BPF_REG_6),
550 BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
551 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xf),
552 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
553 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
554
555 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
556 BPF_ALU64_REG(BPF_SUB, BPF_REG_5, BPF_REG_6),
557
558
559
560 BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
561 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 76),
562
563 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_7),
564
565 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
566 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
567 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
568 BPF_EXIT_INSN(),
569 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
570 BPF_EXIT_INSN(),
571 },
572 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
573 .matches = {
574
575
576
577 {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
578 {10, "R6_w=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
579
580 {11, "R6_w=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},
581
582 {13, "R5_w=pkt(id=1,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c))"},
583
584 {15, "R7_w=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},
585
586 {16, "R5_w=pkt(id=2,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
587
588
589
590
591
592
593 {20, "R5=pkt(id=2,off=0,r=4,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
594 },
595 },
596};
597
598static int probe_filter_length(const struct bpf_insn *fp)
599{
600 int len;
601
602 for (len = MAX_INSNS - 1; len > 0; --len)
603 if (fp[len].code != 0 || fp[len].imm != 0)
604 break;
605 return len + 1;
606}
607
608static char bpf_vlog[32768];
609
610static int do_test_single(struct bpf_align_test *test)
611{
612 struct bpf_insn *prog = test->insns;
613 int prog_type = test->prog_type;
614 char bpf_vlog_copy[32768];
615 const char *line_ptr;
616 int cur_line = -1;
617 int prog_len, i;
618 int fd_prog;
619 int ret;
620
621 prog_len = probe_filter_length(prog);
622 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
623 prog, prog_len, BPF_F_STRICT_ALIGNMENT,
624 "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 2);
625 if (fd_prog < 0 && test->result != REJECT) {
626 printf("Failed to load program.\n");
627 printf("%s", bpf_vlog);
628 ret = 1;
629 } else if (fd_prog >= 0 && test->result == REJECT) {
630 printf("Unexpected success to load!\n");
631 printf("%s", bpf_vlog);
632 ret = 1;
633 close(fd_prog);
634 } else {
635 ret = 0;
636
637 strncpy(bpf_vlog_copy, bpf_vlog, sizeof(bpf_vlog_copy));
638 line_ptr = strtok(bpf_vlog_copy, "\n");
639 for (i = 0; i < MAX_MATCHES; i++) {
640 struct bpf_reg_match m = test->matches[i];
641
642 if (!m.match)
643 break;
644 while (line_ptr) {
645 cur_line = -1;
646 sscanf(line_ptr, "%u: ", &cur_line);
647 if (cur_line == m.line)
648 break;
649 line_ptr = strtok(NULL, "\n");
650 }
651 if (!line_ptr) {
652 printf("Failed to find line %u for match: %s\n",
653 m.line, m.match);
654 ret = 1;
655 printf("%s", bpf_vlog);
656 break;
657 }
658 if (!strstr(line_ptr, m.match)) {
659 printf("Failed to find match %u: %s\n",
660 m.line, m.match);
661 ret = 1;
662 printf("%s", bpf_vlog);
663 break;
664 }
665 }
666 if (fd_prog >= 0)
667 close(fd_prog);
668 }
669 return ret;
670}
671
672static int do_test(unsigned int from, unsigned int to)
673{
674 int all_pass = 0;
675 int all_fail = 0;
676 unsigned int i;
677
678 for (i = from; i < to; i++) {
679 struct bpf_align_test *test = &tests[i];
680 int fail;
681
682 printf("Test %3d: %s ... ",
683 i, test->descr);
684 fail = do_test_single(test);
685 if (fail) {
686 all_fail++;
687 printf("FAIL\n");
688 } else {
689 all_pass++;
690 printf("PASS\n");
691 }
692 }
693 printf("Results: %d pass %d fail\n",
694 all_pass, all_fail);
695 return all_fail ? EXIT_FAILURE : EXIT_SUCCESS;
696}
697
698int main(int argc, char **argv)
699{
700 unsigned int from = 0, to = ARRAY_SIZE(tests);
701
702 if (argc == 3) {
703 unsigned int l = atoi(argv[argc - 2]);
704 unsigned int u = atoi(argv[argc - 1]);
705
706 if (l < to && u < to) {
707 from = l;
708 to = u + 1;
709 }
710 } else if (argc == 2) {
711 unsigned int t = atoi(argv[argc - 1]);
712
713 if (t < to) {
714 from = t;
715 to = t + 1;
716 }
717 }
718 return do_test(from, to);
719}
720