1 /*-
2  * Copyright (c) 2011-2012 Alexander Nasonov.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <bpfjit.h>
31 
32 #include <stdint.h>
33 
34 #include "util.h"
35 #include "tests.h"
36 
37 static void
test_alu_add_k(void)38 test_alu_add_k(void)
39 {
40 	static struct bpf_insn insns[] = {
41 		BPF_STMT(BPF_LD+BPF_IMM, 3),
42 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, 2),
43 		BPF_STMT(BPF_RET+BPF_A, 0)
44 	};
45 
46 	bpfjit_func_t code;
47 	uint8_t pkt[1]; /* the program doesn't read any data */
48 
49 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
50 
51 	CHECK(bpf_validate(insns, insn_count));
52 
53 	code = bpfjit_generate_code(NULL, insns, insn_count);
54 	REQUIRE(code != NULL);
55 
56 	CHECK(jitcall(code, pkt, 1, 1) == 5);
57 
58 	bpfjit_free_code(code);
59 }
60 
61 static void
test_alu_sub_k(void)62 test_alu_sub_k(void)
63 {
64 	static struct bpf_insn insns[] = {
65 		BPF_STMT(BPF_LD+BPF_IMM, 1),
66 		BPF_STMT(BPF_ALU+BPF_SUB+BPF_K, 2),
67 		BPF_STMT(BPF_RET+BPF_A, 0)
68 	};
69 
70 	bpfjit_func_t code;
71 	uint8_t pkt[1]; /* the program doesn't read any data */
72 
73 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
74 
75 	CHECK(bpf_validate(insns, insn_count));
76 
77 	code = bpfjit_generate_code(NULL, insns, insn_count);
78 	REQUIRE(code != NULL);
79 
80 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_MAX);
81 
82 	bpfjit_free_code(code);
83 }
84 
85 static void
test_alu_mul_k(void)86 test_alu_mul_k(void)
87 {
88 	static struct bpf_insn insns[] = {
89 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
90 		BPF_STMT(BPF_ALU+BPF_MUL+BPF_K, 3),
91 		BPF_STMT(BPF_RET+BPF_A, 0)
92 	};
93 
94 	bpfjit_func_t code;
95 	uint8_t pkt[1]; /* the program doesn't read any data */
96 
97 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
98 
99 	CHECK(bpf_validate(insns, insn_count));
100 
101 	code = bpfjit_generate_code(NULL, insns, insn_count);
102 	REQUIRE(code != NULL);
103 
104 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0xfffffffd));
105 
106 	bpfjit_free_code(code);
107 }
108 
109 static void
test_alu_div0_k(void)110 test_alu_div0_k(void)
111 {
112 	static struct bpf_insn insns[] = {
113 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 0),
114 		BPF_STMT(BPF_RET+BPF_A, 0)
115 	};
116 
117 	bpfjit_func_t code;
118 	uint8_t pkt[1]; /* the program doesn't read any data */
119 
120 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
121 
122 	//CHECK(bpf_validate(insns, insn_count));
123 
124 	code = bpfjit_generate_code(NULL, insns, insn_count);
125 	REQUIRE(code != NULL);
126 
127 	CHECK(jitcall(code, pkt, 1, 1) == 0);
128 
129 	bpfjit_free_code(code);
130 }
131 
132 static void
test_alu_div1_k(void)133 test_alu_div1_k(void)
134 {
135 	static struct bpf_insn insns[] = {
136 		BPF_STMT(BPF_LD+BPF_IMM, 7),
137 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 1),
138 		BPF_STMT(BPF_RET+BPF_A, 0)
139 	};
140 
141 	bpfjit_func_t code;
142 	uint8_t pkt[1]; /* the program doesn't read any data */
143 
144 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
145 
146 	CHECK(bpf_validate(insns, insn_count));
147 
148 	code = bpfjit_generate_code(NULL, insns, insn_count);
149 	REQUIRE(code != NULL);
150 
151 	CHECK(jitcall(code, pkt, 1, 1) == 7);
152 
153 	bpfjit_free_code(code);
154 }
155 
156 static void
test_alu_div2_k(void)157 test_alu_div2_k(void)
158 {
159 	static struct bpf_insn insns[] = {
160 		BPF_STMT(BPF_LD+BPF_IMM, 7),
161 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 2),
162 		BPF_STMT(BPF_RET+BPF_A, 0)
163 	};
164 
165 	bpfjit_func_t code;
166 	uint8_t pkt[1]; /* the program doesn't read any data */
167 
168 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
169 
170 	CHECK(bpf_validate(insns, insn_count));
171 
172 	code = bpfjit_generate_code(NULL, insns, insn_count);
173 	REQUIRE(code != NULL);
174 
175 	CHECK(jitcall(code, pkt, 1, 1) == 3);
176 
177 	bpfjit_free_code(code);
178 }
179 
180 static void
test_alu_div4_k(void)181 test_alu_div4_k(void)
182 {
183 	static struct bpf_insn insns[] = {
184 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
185 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 4),
186 		BPF_STMT(BPF_RET+BPF_A, 0)
187 	};
188 
189 	bpfjit_func_t code;
190 	uint8_t pkt[1]; /* the program doesn't read any data */
191 
192 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
193 
194 	CHECK(bpf_validate(insns, insn_count));
195 
196 	code = bpfjit_generate_code(NULL, insns, insn_count);
197 	REQUIRE(code != NULL);
198 
199 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x3fffffff));
200 
201 	bpfjit_free_code(code);
202 }
203 
204 static void
test_alu_div10_k(void)205 test_alu_div10_k(void)
206 {
207 	static struct bpf_insn insns[] = {
208 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
209 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 10),
210 		BPF_STMT(BPF_RET+BPF_A, 0)
211 	};
212 
213 	bpfjit_func_t code;
214 	uint8_t pkt[1]; /* the program doesn't read any data */
215 
216 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
217 
218 	CHECK(bpf_validate(insns, insn_count));
219 
220 	code = bpfjit_generate_code(NULL, insns, insn_count);
221 	REQUIRE(code != NULL);
222 
223 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484384));
224 
225 	bpfjit_free_code(code);
226 }
227 
228 static void
test_alu_div10000_k(void)229 test_alu_div10000_k(void)
230 {
231 	static struct bpf_insn insns[] = {
232 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
233 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 10000),
234 		BPF_STMT(BPF_RET+BPF_A, 0)
235 	};
236 
237 	bpfjit_func_t code;
238 	uint8_t pkt[1]; /* the program doesn't read any data */
239 
240 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
241 
242 	CHECK(bpf_validate(insns, insn_count));
243 
244 	code = bpfjit_generate_code(NULL, insns, insn_count);
245 	REQUIRE(code != NULL);
246 
247 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484));
248 
249 	bpfjit_free_code(code);
250 }
251 
252 static void
test_alu_div7609801_k(void)253 test_alu_div7609801_k(void)
254 {
255 	static struct bpf_insn insns[] = {
256 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294967295)),
257 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, UINT32_C(7609801)),
258 		BPF_STMT(BPF_RET+BPF_A, 0)
259 	};
260 
261 	bpfjit_func_t code;
262 	uint8_t pkt[1]; /* the program doesn't read any data */
263 
264 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
265 
266 	CHECK(bpf_validate(insns, insn_count));
267 
268 	code = bpfjit_generate_code(NULL, insns, insn_count);
269 	REQUIRE(code != NULL);
270 
271 	CHECK(jitcall(code, pkt, 1, 1) == 564);
272 
273 	bpfjit_free_code(code);
274 }
275 
276 static void
test_alu_div0x80000000_k(void)277 test_alu_div0x80000000_k(void)
278 {
279 	static struct bpf_insn insns[] = {
280 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffde)),
281 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, UINT32_C(0x80000000)),
282 		BPF_STMT(BPF_RET+BPF_A, 0)
283 	};
284 
285 	bpfjit_func_t code;
286 	uint8_t pkt[1]; /* the program doesn't read any data */
287 
288 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
289 
290 	CHECK(bpf_validate(insns, insn_count));
291 
292 	code = bpfjit_generate_code(NULL, insns, insn_count);
293 	REQUIRE(code != NULL);
294 
295 	CHECK(jitcall(code, pkt, 1, 1) == 1);
296 
297 	bpfjit_free_code(code);
298 }
299 
300 static void
test_alu_and_k(void)301 test_alu_and_k(void)
302 {
303 	static struct bpf_insn insns[] = {
304 		BPF_STMT(BPF_LD+BPF_IMM, 0xdead),
305 		BPF_STMT(BPF_ALU+BPF_AND+BPF_K, 0xbeef),
306 		BPF_STMT(BPF_RET+BPF_A, 0)
307 	};
308 
309 	bpfjit_func_t code;
310 	uint8_t pkt[1]; /* the program doesn't read any data */
311 
312 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
313 
314 	CHECK(bpf_validate(insns, insn_count));
315 
316 	code = bpfjit_generate_code(NULL, insns, insn_count);
317 	REQUIRE(code != NULL);
318 
319 	CHECK(jitcall(code, pkt, 1, 1) == (0xdead&0xbeef));
320 
321 	bpfjit_free_code(code);
322 }
323 
324 static void
test_alu_or_k(void)325 test_alu_or_k(void)
326 {
327 	static struct bpf_insn insns[] = {
328 		BPF_STMT(BPF_LD+BPF_IMM, 0xdead0000),
329 		BPF_STMT(BPF_ALU+BPF_OR+BPF_K, 0x0000beef),
330 		BPF_STMT(BPF_RET+BPF_A, 0)
331 	};
332 
333 	bpfjit_func_t code;
334 	uint8_t pkt[1]; /* the program doesn't read any data */
335 
336 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
337 
338 	CHECK(bpf_validate(insns, insn_count));
339 
340 	code = bpfjit_generate_code(NULL, insns, insn_count);
341 	REQUIRE(code != NULL);
342 
343 	CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
344 
345 	bpfjit_free_code(code);
346 }
347 
348 static void
test_alu_lsh_k(void)349 test_alu_lsh_k(void)
350 {
351 	static struct bpf_insn insns[] = {
352 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
353 		BPF_STMT(BPF_ALU+BPF_LSH+BPF_K, 16),
354 		BPF_STMT(BPF_RET+BPF_A, 0)
355 	};
356 
357 	bpfjit_func_t code;
358 	uint8_t pkt[1]; /* the program doesn't read any data */
359 
360 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
361 
362 	CHECK(bpf_validate(insns, insn_count));
363 
364 	code = bpfjit_generate_code(NULL, insns, insn_count);
365 	REQUIRE(code != NULL);
366 
367 	CHECK(jitcall(code, pkt, 1, 1) == 0xbeef0000);
368 
369 	bpfjit_free_code(code);
370 }
371 
372 static void
test_alu_lsh0_k(void)373 test_alu_lsh0_k(void)
374 {
375 	static struct bpf_insn insns[] = {
376 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
377 		BPF_STMT(BPF_ALU+BPF_LSH+BPF_K, 0),
378 		BPF_STMT(BPF_RET+BPF_A, 0)
379 	};
380 
381 	bpfjit_func_t code;
382 	uint8_t pkt[1]; /* the program doesn't read any data */
383 
384 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
385 
386 	CHECK(bpf_validate(insns, insn_count));
387 
388 	code = bpfjit_generate_code(NULL, insns, insn_count);
389 	REQUIRE(code != NULL);
390 
391 	CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
392 
393 	bpfjit_free_code(code);
394 }
395 
396 static void
test_alu_rsh_k(void)397 test_alu_rsh_k(void)
398 {
399 	static struct bpf_insn insns[] = {
400 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
401 		BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 16),
402 		BPF_STMT(BPF_RET+BPF_A, 0)
403 	};
404 
405 	bpfjit_func_t code;
406 	uint8_t pkt[1]; /* the program doesn't read any data */
407 
408 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
409 
410 	CHECK(bpf_validate(insns, insn_count));
411 
412 	code = bpfjit_generate_code(NULL, insns, insn_count);
413 	REQUIRE(code != NULL);
414 
415 	CHECK(jitcall(code, pkt, 1, 1) == 0x0000dead);
416 
417 	bpfjit_free_code(code);
418 }
419 
420 static void
test_alu_rsh0_k(void)421 test_alu_rsh0_k(void)
422 {
423 	static struct bpf_insn insns[] = {
424 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
425 		BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 0),
426 		BPF_STMT(BPF_RET+BPF_A, 0)
427 	};
428 
429 	bpfjit_func_t code;
430 	uint8_t pkt[1]; /* the program doesn't read any data */
431 
432 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
433 
434 	CHECK(bpf_validate(insns, insn_count));
435 
436 	code = bpfjit_generate_code(NULL, insns, insn_count);
437 	REQUIRE(code != NULL);
438 
439 	CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
440 
441 	bpfjit_free_code(code);
442 }
443 
444 static void
test_alu_modulo_k(void)445 test_alu_modulo_k(void)
446 {
447 	static struct bpf_insn insns[] = {
448 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0x7fffff77)),
449 
450 		/* (7FFFFF77 * 0FFFFF77) = 07FFFFB2,F0004951 */
451 		BPF_STMT(BPF_ALU+BPF_MUL+BPF_K, UINT32_C(0x0fffff77)),
452 
453 		/* 07FFFFB2,F0004951 << 1 = 0FFFFF65,E00092A2 */
454 		BPF_STMT(BPF_ALU+BPF_LSH+BPF_K, 1),
455 
456 		/* 0FFFFF65,E00092A2 + DDDDDDDD = 0FFFFF66,BDDE707F */
457 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, UINT32_C(0xdddddddd)),
458 
459 		/* 0FFFFF66,BDDE707F - FFFFFFFF = 0FFFFF65,BDDE7080 */
460 		BPF_STMT(BPF_ALU+BPF_SUB+BPF_K, UINT32_C(0xffffffff)),
461 
462 		/* 0FFFFF65,BDDE7080 | 0000030C = 0FFFFF65,BDDE738C */
463 		BPF_STMT(BPF_ALU+BPF_OR+BPF_K, UINT32_C(0x0000030c)),
464 
465 		/* -0FFFFF65,BDDE738C mod(2^64) = F000009A,42218C74 */
466 		BPF_STMT(BPF_ALU+BPF_NEG, 0),
467 
468 		/* F000009A,42218C74 & FFFFFF0F = F000009A,42218C04 */
469 		BPF_STMT(BPF_ALU+BPF_AND+BPF_K, UINT32_C(0xffffff0f)),
470 
471 		/* F000009A,42218C74 >> 3 = 1E000013,48443180 */
472 		/* 00000000,42218C74 >> 3 = 00000000,08443180 */
473 		BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 3),
474 
475 		/* 00000000,08443180 * 7FFFFF77 = 042218BB,93818280 */
476 		BPF_STMT(BPF_ALU+BPF_MUL+BPF_K, UINT32_C(0x7fffff77)),
477 
478 		/* 042218BB,93818280 / DEAD = 000004C0,71CBBBC3 */
479 		/* 00000000,93818280 / DEAD = 00000000,0000A994 */
480 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, UINT32_C(0xdead)),
481 
482 		BPF_STMT(BPF_RET+BPF_A, 0)
483 	};
484 
485 	bpfjit_func_t code;
486 	uint8_t pkt[1]; /* the program doesn't read any data */
487 
488 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
489 
490 	CHECK(bpf_validate(insns, insn_count));
491 
492 	code = bpfjit_generate_code(NULL, insns, insn_count);
493 	REQUIRE(code != NULL);
494 
495 	CHECK(jitcall(code, pkt, 1, 1) != UINT32_C(0x71cbbbc3));
496 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x0000a994));
497 
498 
499 	bpfjit_free_code(code);
500 }
501 
502 static void
test_alu_add_x(void)503 test_alu_add_x(void)
504 {
505 	static struct bpf_insn insns[] = {
506 		BPF_STMT(BPF_LD+BPF_IMM, 3),
507 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2),
508 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
509 		BPF_STMT(BPF_RET+BPF_A, 0)
510 	};
511 
512 	bpfjit_func_t code;
513 	uint8_t pkt[1]; /* the program doesn't read any data */
514 
515 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
516 
517 	CHECK(bpf_validate(insns, insn_count));
518 
519 	code = bpfjit_generate_code(NULL, insns, insn_count);
520 	REQUIRE(code != NULL);
521 
522 	CHECK(jitcall(code, pkt, 1, 1) == 5);
523 
524 	bpfjit_free_code(code);
525 }
526 
527 static void
test_alu_sub_x(void)528 test_alu_sub_x(void)
529 {
530 	static struct bpf_insn insns[] = {
531 		BPF_STMT(BPF_LD+BPF_IMM, 1),
532 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2),
533 		BPF_STMT(BPF_ALU+BPF_SUB+BPF_X, 0),
534 		BPF_STMT(BPF_RET+BPF_A, 0)
535 	};
536 
537 	bpfjit_func_t code;
538 	uint8_t pkt[1]; /* the program doesn't read any data */
539 
540 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
541 
542 	CHECK(bpf_validate(insns, insn_count));
543 
544 	code = bpfjit_generate_code(NULL, insns, insn_count);
545 	REQUIRE(code != NULL);
546 
547 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_MAX);
548 
549 	bpfjit_free_code(code);
550 }
551 
552 static void
test_alu_mul_x(void)553 test_alu_mul_x(void)
554 {
555 	static struct bpf_insn insns[] = {
556 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
557 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 3),
558 		BPF_STMT(BPF_ALU+BPF_MUL+BPF_X, 0),
559 		BPF_STMT(BPF_RET+BPF_A, 0)
560 	};
561 
562 	bpfjit_func_t code;
563 	uint8_t pkt[1]; /* the program doesn't read any data */
564 
565 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
566 
567 	CHECK(bpf_validate(insns, insn_count));
568 
569 	code = bpfjit_generate_code(NULL, insns, insn_count);
570 	REQUIRE(code != NULL);
571 
572 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0xfffffffd));
573 
574 	bpfjit_free_code(code);
575 }
576 
577 static void
test_alu_div0_x(void)578 test_alu_div0_x(void)
579 {
580 	static struct bpf_insn insns[] = {
581 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0),
582 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
583 		BPF_STMT(BPF_RET+BPF_A, 0)
584 	};
585 
586 	bpfjit_func_t code;
587 	uint8_t pkt[1]; /* the program doesn't read any data */
588 
589 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
590 
591 	CHECK(bpf_validate(insns, insn_count));
592 
593 	code = bpfjit_generate_code(NULL, insns, insn_count);
594 	REQUIRE(code != NULL);
595 
596 	CHECK(jitcall(code, pkt, 1, 1) == 0);
597 
598 	bpfjit_free_code(code);
599 }
600 
601 static void
test_alu_div1_x(void)602 test_alu_div1_x(void)
603 {
604 	static struct bpf_insn insns[] = {
605 		BPF_STMT(BPF_LD+BPF_IMM, 7),
606 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 1),
607 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
608 		BPF_STMT(BPF_RET+BPF_A, 0)
609 	};
610 
611 	bpfjit_func_t code;
612 	uint8_t pkt[1]; /* the program doesn't read any data */
613 
614 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
615 
616 	CHECK(bpf_validate(insns, insn_count));
617 
618 	code = bpfjit_generate_code(NULL, insns, insn_count);
619 	REQUIRE(code != NULL);
620 
621 	CHECK(jitcall(code, pkt, 1, 1) == 7);
622 
623 	bpfjit_free_code(code);
624 }
625 
626 static void
test_alu_div2_x(void)627 test_alu_div2_x(void)
628 {
629 	static struct bpf_insn insns[] = {
630 		BPF_STMT(BPF_LD+BPF_IMM, 7),
631 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2),
632 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
633 		BPF_STMT(BPF_RET+BPF_A, 0)
634 	};
635 
636 	bpfjit_func_t code;
637 	uint8_t pkt[1]; /* the program doesn't read any data */
638 
639 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
640 
641 	CHECK(bpf_validate(insns, insn_count));
642 
643 	code = bpfjit_generate_code(NULL, insns, insn_count);
644 	REQUIRE(code != NULL);
645 
646 	CHECK(jitcall(code, pkt, 1, 1) == 3);
647 
648 	bpfjit_free_code(code);
649 }
650 
651 static void
test_alu_div4_x(void)652 test_alu_div4_x(void)
653 {
654 	static struct bpf_insn insns[] = {
655 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
656 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 4),
657 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
658 		BPF_STMT(BPF_RET+BPF_A, 0)
659 	};
660 
661 	bpfjit_func_t code;
662 	uint8_t pkt[1]; /* the program doesn't read any data */
663 
664 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
665 
666 	CHECK(bpf_validate(insns, insn_count));
667 
668 	code = bpfjit_generate_code(NULL, insns, insn_count);
669 	REQUIRE(code != NULL);
670 
671 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x3fffffff));
672 
673 	bpfjit_free_code(code);
674 }
675 
676 static void
test_alu_div10_x(void)677 test_alu_div10_x(void)
678 {
679 	static struct bpf_insn insns[] = {
680 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
681 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 10),
682 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
683 		BPF_STMT(BPF_RET+BPF_A, 0)
684 	};
685 
686 	bpfjit_func_t code;
687 	uint8_t pkt[1]; /* the program doesn't read any data */
688 
689 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
690 
691 	CHECK(bpf_validate(insns, insn_count));
692 
693 	code = bpfjit_generate_code(NULL, insns, insn_count);
694 	REQUIRE(code != NULL);
695 
696 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484384));
697 
698 	bpfjit_free_code(code);
699 }
700 
701 static void
test_alu_div10000_x(void)702 test_alu_div10000_x(void)
703 {
704 	static struct bpf_insn insns[] = {
705 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
706 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 10000),
707 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
708 		BPF_STMT(BPF_RET+BPF_A, 0)
709 	};
710 
711 	bpfjit_func_t code;
712 	uint8_t pkt[1]; /* the program doesn't read any data */
713 
714 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
715 
716 	CHECK(bpf_validate(insns, insn_count));
717 
718 	code = bpfjit_generate_code(NULL, insns, insn_count);
719 	REQUIRE(code != NULL);
720 
721 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484));
722 
723 	bpfjit_free_code(code);
724 }
725 
726 static void
test_alu_div7609801_x(void)727 test_alu_div7609801_x(void)
728 {
729 	static struct bpf_insn insns[] = {
730 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294967295)),
731 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, UINT32_C(7609801)),
732 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
733 		BPF_STMT(BPF_RET+BPF_A, 0)
734 	};
735 
736 	bpfjit_func_t code;
737 	uint8_t pkt[1]; /* the program doesn't read any data */
738 
739 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
740 
741 	CHECK(bpf_validate(insns, insn_count));
742 
743 	code = bpfjit_generate_code(NULL, insns, insn_count);
744 	REQUIRE(code != NULL);
745 
746 	CHECK(jitcall(code, pkt, 1, 1) == 564);
747 
748 	bpfjit_free_code(code);
749 }
750 
751 static void
test_alu_div0x80000000_x(void)752 test_alu_div0x80000000_x(void)
753 {
754 	static struct bpf_insn insns[] = {
755 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_MAX - 33),
756 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, UINT32_C(0x80000000)),
757 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
758 		BPF_STMT(BPF_RET+BPF_A, 0)
759 	};
760 
761 	bpfjit_func_t code;
762 	uint8_t pkt[1]; /* the program doesn't read any data */
763 
764 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
765 
766 	CHECK(bpf_validate(insns, insn_count));
767 
768 	code = bpfjit_generate_code(NULL, insns, insn_count);
769 	REQUIRE(code != NULL);
770 
771 	CHECK(jitcall(code, pkt, 1, 1) == 1);
772 
773 	bpfjit_free_code(code);
774 }
775 
776 static void
test_alu_and_x(void)777 test_alu_and_x(void)
778 {
779 	static struct bpf_insn insns[] = {
780 		BPF_STMT(BPF_LD+BPF_IMM, 0xdead),
781 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0xbeef),
782 		BPF_STMT(BPF_ALU+BPF_AND+BPF_X, 0),
783 		BPF_STMT(BPF_RET+BPF_A, 0)
784 	};
785 
786 	bpfjit_func_t code;
787 	uint8_t pkt[1]; /* the program doesn't read any data */
788 
789 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
790 
791 	CHECK(bpf_validate(insns, insn_count));
792 
793 	code = bpfjit_generate_code(NULL, insns, insn_count);
794 	REQUIRE(code != NULL);
795 
796 	CHECK(jitcall(code, pkt, 1, 1) == (0xdead&0xbeef));
797 
798 	bpfjit_free_code(code);
799 }
800 
801 static void
test_alu_or_x(void)802 test_alu_or_x(void)
803 {
804 	static struct bpf_insn insns[] = {
805 		BPF_STMT(BPF_LD+BPF_IMM, 0xdead0000),
806 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0x0000beef),
807 		BPF_STMT(BPF_ALU+BPF_OR+BPF_X, 0),
808 		BPF_STMT(BPF_RET+BPF_A, 0)
809 	};
810 
811 	bpfjit_func_t code;
812 	uint8_t pkt[1]; /* the program doesn't read any data */
813 
814 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
815 
816 	CHECK(bpf_validate(insns, insn_count));
817 
818 	code = bpfjit_generate_code(NULL, insns, insn_count);
819 	REQUIRE(code != NULL);
820 
821 	CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
822 
823 	bpfjit_free_code(code);
824 }
825 
826 static void
test_alu_lsh_x(void)827 test_alu_lsh_x(void)
828 {
829 	static struct bpf_insn insns[] = {
830 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
831 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 16),
832 		BPF_STMT(BPF_ALU+BPF_LSH+BPF_X, 0),
833 		BPF_STMT(BPF_RET+BPF_A, 0)
834 	};
835 
836 	bpfjit_func_t code;
837 	uint8_t pkt[1]; /* the program doesn't read any data */
838 
839 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
840 
841 	CHECK(bpf_validate(insns, insn_count));
842 
843 	code = bpfjit_generate_code(NULL, insns, insn_count);
844 	REQUIRE(code != NULL);
845 
846 	CHECK(jitcall(code, pkt, 1, 1) == 0xbeef0000);
847 
848 	bpfjit_free_code(code);
849 }
850 
851 static void
test_alu_lsh0_x(void)852 test_alu_lsh0_x(void)
853 {
854 	static struct bpf_insn insns[] = {
855 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
856 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0),
857 		BPF_STMT(BPF_ALU+BPF_LSH+BPF_X, 0),
858 		BPF_STMT(BPF_RET+BPF_A, 0)
859 	};
860 
861 	bpfjit_func_t code;
862 	uint8_t pkt[1]; /* the program doesn't read any data */
863 
864 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
865 
866 	CHECK(bpf_validate(insns, insn_count));
867 
868 	code = bpfjit_generate_code(NULL, insns, insn_count);
869 	REQUIRE(code != NULL);
870 
871 	CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
872 
873 	bpfjit_free_code(code);
874 }
875 
876 static void
test_alu_rsh_x(void)877 test_alu_rsh_x(void)
878 {
879 	static struct bpf_insn insns[] = {
880 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
881 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 16),
882 		BPF_STMT(BPF_ALU+BPF_RSH+BPF_X, 0),
883 		BPF_STMT(BPF_RET+BPF_A, 0)
884 	};
885 
886 	bpfjit_func_t code;
887 	uint8_t pkt[1]; /* the program doesn't read any data */
888 
889 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
890 
891 	CHECK(bpf_validate(insns, insn_count));
892 
893 	code = bpfjit_generate_code(NULL, insns, insn_count);
894 	REQUIRE(code != NULL);
895 
896 	CHECK(jitcall(code, pkt, 1, 1) == 0x0000dead);
897 
898 	bpfjit_free_code(code);
899 }
900 
901 static void
test_alu_rsh0_x(void)902 test_alu_rsh0_x(void)
903 {
904 	static struct bpf_insn insns[] = {
905 		BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
906 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0),
907 		BPF_STMT(BPF_ALU+BPF_RSH+BPF_X, 0),
908 		BPF_STMT(BPF_RET+BPF_A, 0)
909 	};
910 
911 	bpfjit_func_t code;
912 	uint8_t pkt[1]; /* the program doesn't read any data */
913 
914 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
915 
916 	CHECK(bpf_validate(insns, insn_count));
917 
918 	code = bpfjit_generate_code(NULL, insns, insn_count);
919 	REQUIRE(code != NULL);
920 
921 	CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
922 
923 	bpfjit_free_code(code);
924 }
925 
926 static void
test_alu_neg(void)927 test_alu_neg(void)
928 {
929 	static struct bpf_insn insns[] = {
930 		BPF_STMT(BPF_LD+BPF_IMM, 777),
931 		BPF_STMT(BPF_ALU+BPF_NEG, 0),
932 		BPF_STMT(BPF_RET+BPF_A, 0)
933 	};
934 
935 	bpfjit_func_t code;
936 	uint8_t pkt[1]; /* the program doesn't read any data */
937 
938 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
939 
940 	CHECK(bpf_validate(insns, insn_count));
941 
942 	code = bpfjit_generate_code(NULL, insns, insn_count);
943 	REQUIRE(code != NULL);
944 
945 	CHECK(jitcall(code, pkt, 1, 1) == 0u-777u);
946 
947 	bpfjit_free_code(code);
948 }
949 
950 static void
test_alu_modulo_x(void)951 test_alu_modulo_x(void)
952 {
953 	static struct bpf_insn insns[] = {
954 		BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0x7fffff77)),
955 
956 		/* (7FFFFF77 * 0FFFFF77) = 07FFFFB2,F0004951 */
957 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0x0fffff77)),
958 		BPF_STMT(BPF_ALU+BPF_MUL+BPF_X, 0),
959 
960 		/* 07FFFFB2,F0004951 << 1 = 0FFFFF65,E00092A2 */
961 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, 1),
962 		BPF_STMT(BPF_ALU+BPF_LSH+BPF_X, 0),
963 
964 		/* 0FFFFF65,E00092A2 + DDDDDDDD = 0FFFFF66,BDDE707F */
965 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xdddddddd)),
966 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
967 
968 		/* 0FFFFF66,BDDE707F - FFFFFFFF = 0FFFFF65,BDDE7080 */
969 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xffffffff)),
970 		BPF_STMT(BPF_ALU+BPF_SUB+BPF_X, 0),
971 
972 		/* 0FFFFF65,BDDE7080 | 0000030C = 0FFFFF65,BDDE738C */
973 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0x0000030c)),
974 		BPF_STMT(BPF_ALU+BPF_OR+BPF_X, 0),
975 
976 		/* -0FFFFF65,BDDE738C mod(2^64) = F000009A,42218C74 */
977 		BPF_STMT(BPF_ALU+BPF_NEG, 0),
978 
979 		/* F000009A,42218C74 & FFFFFF0F = F000009A,42218C04 */
980 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xffffff0f)),
981 		BPF_STMT(BPF_ALU+BPF_AND+BPF_X, 0),
982 
983 		/* F000009A,42218C74 >> 3 = 1E000013,48443180 */
984 		/* 00000000,42218C74 >> 3 = 00000000,08443180 */
985 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, 3),
986 		BPF_STMT(BPF_ALU+BPF_RSH+BPF_X, 0),
987 
988 		/* 00000000,08443180 * 7FFFFF77 = 042218BB,93818280 */
989 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0x7fffff77)),
990 		BPF_STMT(BPF_ALU+BPF_MUL+BPF_X, 0),
991 
992 		/* 042218BB,93818280 / DEAD = 000004C0,71CBBBC3 */
993 		/* 00000000,93818280 / DEAD = 00000000,0000A994 */
994 		BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xdead)),
995 		BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
996 
997 		BPF_STMT(BPF_RET+BPF_A, 0)
998 	};
999 
1000 	bpfjit_func_t code;
1001 	uint8_t pkt[1]; /* the program doesn't read any data */
1002 
1003 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
1004 
1005 	CHECK(bpf_validate(insns, insn_count));
1006 
1007 	code = bpfjit_generate_code(NULL, insns, insn_count);
1008 	REQUIRE(code != NULL);
1009 
1010 	CHECK(jitcall(code, pkt, 1, 1) != UINT32_C(0x71cbbbc3));
1011 	CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x0000a994));
1012 
1013 
1014 	bpfjit_free_code(code);
1015 }
1016 
1017 void
test_alu(void)1018 test_alu(void)
1019 {
1020 
1021 	test_alu_add_k();
1022 	test_alu_sub_k();
1023 	test_alu_mul_k();
1024 	test_alu_div0_k();
1025 	test_alu_div1_k();
1026 	test_alu_div2_k();
1027 	test_alu_div4_k();
1028 	test_alu_div10_k();
1029 	test_alu_div10000_k();
1030 	test_alu_div7609801_k();
1031 	test_alu_div0x80000000_k();
1032 	test_alu_and_k();
1033 	test_alu_or_k();
1034 	test_alu_lsh_k();
1035 	test_alu_lsh0_k();
1036 	test_alu_rsh_k();
1037 	test_alu_rsh0_k();
1038 	test_alu_modulo_k();
1039 
1040 	test_alu_add_x();
1041 	test_alu_sub_x();
1042 	test_alu_mul_x();
1043 	test_alu_div0_x();
1044 	test_alu_div1_x();
1045 	test_alu_div2_x();
1046 	test_alu_div4_x();
1047 	test_alu_div10_x();
1048 	test_alu_div10000_x();
1049 	test_alu_div7609801_x();
1050 	test_alu_div0x80000000_x();
1051 	test_alu_and_x();
1052 	test_alu_or_x();
1053 	test_alu_lsh_x();
1054 	test_alu_lsh0_x();
1055 	test_alu_rsh_x();
1056 	test_alu_rsh0_x();
1057 	test_alu_modulo_x();
1058 
1059 	test_alu_neg();
1060 }
1061