t_cop.c revision 314817
1/* $NetBSD: t_cop.c,v 1.4 2017/01/13 21:30:42 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2014 Alexander Nasonov. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__RCSID("$NetBSD: t_cop.c,v 1.4 2017/01/13 21:30:42 christos Exp $"); 34 35#include <stdint.h> 36#include <string.h> 37 38#define __BPF_PRIVATE 39#include <net/bpf.h> 40#include <net/bpfjit.h> 41 42#include "../../net/bpf/h_bpf.h" 43 44/* XXX: atf-c.h has collisions with mbuf */ 45#undef m_type 46#undef m_data 47#include <atf-c.h> 48 49#include "h_macros.h" 50 51static uint32_t retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 52static uint32_t retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 53static uint32_t retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 54static uint32_t retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 55static uint32_t setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 56 57static const bpf_copfunc_t copfuncs[] = { 58 &retA, 59 &retBL, 60 &retWL, 61 &retNF, 62 &setARG 63}; 64 65static const bpf_ctx_t ctx = { 66 .copfuncs = copfuncs, 67 .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]), 68 .extwords = 0 69}; 70 71static uint32_t 72retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 73{ 74 75 return A; 76} 77 78static uint32_t 79retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 80{ 81 82 return args->buflen; 83} 84 85static uint32_t 86retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 87{ 88 89 return args->wirelen; 90} 91 92static uint32_t 93retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 94{ 95 96 return bc->nfuncs; 97} 98 99/* 100 * COP function with a side effect. 101 */ 102static uint32_t 103setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 104{ 105 bool *arg = (bool *)args->arg; 106 bool old = *arg; 107 108 *arg = true; 109 return old; 110} 111 112ATF_TC(bpfjit_cop_no_ctx); 113ATF_TC_HEAD(bpfjit_cop_no_ctx, tc) 114{ 115 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COP " 116 "instruction isn't valid without a context"); 117} 118 119ATF_TC_BODY(bpfjit_cop_no_ctx, tc) 120{ 121 static struct bpf_insn insns[] = { 122 BPF_STMT(BPF_MISC+BPF_COP, 0), 123 BPF_STMT(BPF_RET+BPF_K, 7) 124 }; 125 126 bpfjit_func_t code; 127 128 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 129 130 RZ(rump_init()); 131 132 ATF_CHECK(!prog_validate(insns, insn_count)); 133 134 rump_schedule(); 135 code = rumpns_bpfjit_generate_code(NULL, insns, insn_count); 136 rump_unschedule(); 137 ATF_CHECK(code == NULL); 138} 139 140ATF_TC(bpfjit_cop_ret_A); 141ATF_TC_HEAD(bpfjit_cop_ret_A, tc) 142{ 143 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 144 "that returns a content of the A register"); 145} 146 147ATF_TC_BODY(bpfjit_cop_ret_A, tc) 148{ 149 static struct bpf_insn insns[] = { 150 BPF_STMT(BPF_LD+BPF_IMM, 13), 151 BPF_STMT(BPF_MISC+BPF_COP, 0), // retA 152 BPF_STMT(BPF_RET+BPF_A, 0) 153 }; 154 155 bpfjit_func_t code; 156 uint8_t pkt[1] = { 0 }; 157 bpf_args_t args = { 158 .pkt = pkt, 159 .buflen = sizeof(pkt), 160 .wirelen = sizeof(pkt), 161 }; 162 163 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 164 165 RZ(rump_init()); 166 167 rump_schedule(); 168 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 169 rump_unschedule(); 170 ATF_REQUIRE(code != NULL); 171 172 ATF_CHECK(code(&ctx, &args) == 13); 173 174 rump_schedule(); 175 rumpns_bpfjit_free_code(code); 176 rump_unschedule(); 177} 178 179ATF_TC(bpfjit_cop_ret_buflen); 180ATF_TC_HEAD(bpfjit_cop_ret_buflen, tc) 181{ 182 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 183 "that returns the buflen argument"); 184} 185 186ATF_TC_BODY(bpfjit_cop_ret_buflen, tc) 187{ 188 static struct bpf_insn insns[] = { 189 BPF_STMT(BPF_LD+BPF_IMM, 13), 190 BPF_STMT(BPF_MISC+BPF_COP, 1), // retBL 191 BPF_STMT(BPF_RET+BPF_A, 0) 192 }; 193 194 bpfjit_func_t code; 195 uint8_t pkt[1] = { 0 }; 196 bpf_args_t args = { 197 .pkt = pkt, 198 .buflen = sizeof(pkt), 199 .wirelen = sizeof(pkt) 200 }; 201 202 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 203 204 RZ(rump_init()); 205 206 rump_schedule(); 207 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 208 rump_unschedule(); 209 ATF_REQUIRE(code != NULL); 210 211 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 212 213 rump_schedule(); 214 rumpns_bpfjit_free_code(code); 215 rump_unschedule(); 216} 217 218ATF_TC(bpfjit_cop_ret_wirelen); 219ATF_TC_HEAD(bpfjit_cop_ret_wirelen, tc) 220{ 221 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 222 "that returns the wirelen argument"); 223} 224 225ATF_TC_BODY(bpfjit_cop_ret_wirelen, tc) 226{ 227 static struct bpf_insn insns[] = { 228 BPF_STMT(BPF_LD+BPF_IMM, 13), 229 BPF_STMT(BPF_MISC+BPF_COP, 2), // retWL 230 BPF_STMT(BPF_RET+BPF_A, 0) 231 }; 232 233 bpfjit_func_t code; 234 uint8_t pkt[1] = { 0 }; 235 bpf_args_t args = { 236 .pkt = pkt, 237 .buflen = sizeof(pkt), 238 .wirelen = sizeof(pkt) 239 }; 240 241 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 242 243 RZ(rump_init()); 244 245 rump_schedule(); 246 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 247 rump_unschedule(); 248 ATF_REQUIRE(code != NULL); 249 250 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 251 252 rump_schedule(); 253 rumpns_bpfjit_free_code(code); 254 rump_unschedule(); 255} 256 257ATF_TC(bpfjit_cop_ret_nfuncs); 258ATF_TC_HEAD(bpfjit_cop_ret_nfuncs, tc) 259{ 260 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 261 "that returns nfuncs member of the context argument"); 262} 263 264ATF_TC_BODY(bpfjit_cop_ret_nfuncs, tc) 265{ 266 static struct bpf_insn insns[] = { 267 BPF_STMT(BPF_LD+BPF_IMM, 13), 268 BPF_STMT(BPF_MISC+BPF_COP, 3), // retNF 269 BPF_STMT(BPF_RET+BPF_A, 0) 270 }; 271 272 bpfjit_func_t code; 273 uint8_t pkt[1] = { 0 }; 274 bpf_args_t args = { 275 .pkt = pkt, 276 .buflen = sizeof(pkt), 277 .wirelen = sizeof(pkt) 278 }; 279 280 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 281 282 RZ(rump_init()); 283 284 rump_schedule(); 285 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 286 rump_unschedule(); 287 ATF_REQUIRE(code != NULL); 288 289 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs); 290 291 rump_schedule(); 292 rumpns_bpfjit_free_code(code); 293 rump_unschedule(); 294} 295 296ATF_TC(bpfjit_cop_side_effect); 297ATF_TC_HEAD(bpfjit_cop_side_effect, tc) 298{ 299 atf_tc_set_md_var(tc, "descr", 300 "Test that ABC optimization doesn't skip BPF_COP call"); 301} 302 303ATF_TC_BODY(bpfjit_cop_side_effect, tc) 304{ 305 static struct bpf_insn insns[] = { 306 BPF_STMT(BPF_LD+BPF_IMM, 13), 307 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), 308 BPF_STMT(BPF_MISC+BPF_COP, 4), // setARG 309 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999), 310 BPF_STMT(BPF_RET+BPF_A, 0) 311 }; 312 313 bpfjit_func_t code; 314 bool arg = false; 315 uint8_t pkt[1] = { 0 }; 316 bpf_args_t args = { 317 .pkt = pkt, 318 .buflen = sizeof(pkt), 319 .wirelen = sizeof(pkt), 320 .mem = NULL, 321 .arg = &arg 322 }; 323 324 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 325 326 RZ(rump_init()); 327 328 rump_schedule(); 329 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 330 rump_unschedule(); 331 ATF_REQUIRE(code != NULL); 332 333 ATF_CHECK(code(&ctx, &args) == 0); 334 ATF_CHECK(arg == true); 335 336 rump_schedule(); 337 rumpns_bpfjit_free_code(code); 338 rump_unschedule(); 339} 340 341ATF_TC(bpfjit_cop_copx); 342ATF_TC_HEAD(bpfjit_cop_copx, tc) 343{ 344 atf_tc_set_md_var(tc, "descr", 345 "Test BPF_COP call followed by BPF_COPX call"); 346} 347 348ATF_TC_BODY(bpfjit_cop_copx, tc) 349{ 350 static struct bpf_insn insns[] = { 351 BPF_STMT(BPF_LD+BPF_IMM, 1), /* A <- 1 */ 352 BPF_STMT(BPF_MISC+BPF_COP, 0), /* retA */ 353 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 354 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */ 355 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 356 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 357 BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retNF */ 358 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 359 BPF_STMT(BPF_RET+BPF_A, 0) 360 }; 361 362 bpfjit_func_t code; 363 uint8_t pkt[1] = { 2 }; 364 bpf_args_t args = { 365 .pkt = pkt, 366 .buflen = sizeof(pkt), 367 .wirelen = sizeof(pkt), 368 }; 369 370 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 371 372 RZ(rump_init()); 373 374 rump_schedule(); 375 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 376 rump_unschedule(); 377 ATF_REQUIRE(code != NULL); 378 379 ATF_CHECK(code(&ctx, &args) == 3 + ctx.nfuncs); 380 381 rump_schedule(); 382 rumpns_bpfjit_free_code(code); 383 rump_unschedule(); 384} 385 386ATF_TC(bpfjit_cop_invalid_index); 387ATF_TC_HEAD(bpfjit_cop_invalid_index, tc) 388{ 389 atf_tc_set_md_var(tc, "descr", 390 "Test that out-of-range coprocessor function fails validation"); 391} 392 393ATF_TC_BODY(bpfjit_cop_invalid_index, tc) 394{ 395 static struct bpf_insn insns[] = { 396 BPF_STMT(BPF_LD+BPF_IMM, 13), 397 BPF_STMT(BPF_MISC+BPF_COP, 6), // invalid index 398 BPF_STMT(BPF_RET+BPF_K, 27) 399 }; 400 401 bpfjit_func_t code; 402 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 403 404 RZ(rump_init()); 405 406 rump_schedule(); 407 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 408 rump_unschedule(); 409 ATF_CHECK(code == NULL); 410} 411 412ATF_TC(bpfjit_copx_no_ctx); 413ATF_TC_HEAD(bpfjit_copx_no_ctx, tc) 414{ 415 atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COPX " 416 "instruction isn't valid without a context"); 417} 418 419ATF_TC_BODY(bpfjit_copx_no_ctx, tc) 420{ 421 static struct bpf_insn insns[] = { 422 BPF_STMT(BPF_MISC+BPF_COP, 0), 423 BPF_STMT(BPF_RET+BPF_K, 7) 424 }; 425 426 bpfjit_func_t code; 427 428 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 429 430 RZ(rump_init()); 431 432 ATF_CHECK(!prog_validate(insns, insn_count)); 433 434 rump_schedule(); 435 code = rumpns_bpfjit_generate_code(NULL, insns, insn_count); 436 rump_unschedule(); 437 ATF_CHECK(code == NULL); 438} 439 440ATF_TC(bpfjit_copx_ret_A); 441ATF_TC_HEAD(bpfjit_copx_ret_A, tc) 442{ 443 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 444 "that returns a content of the A register"); 445} 446 447ATF_TC_BODY(bpfjit_copx_ret_A, tc) 448{ 449 static struct bpf_insn insns[] = { 450 BPF_STMT(BPF_LD+BPF_IMM, 13), 451 BPF_STMT(BPF_LDX+BPF_IMM, 0), // retA 452 BPF_STMT(BPF_MISC+BPF_COPX, 0), 453 BPF_STMT(BPF_RET+BPF_A, 0) 454 }; 455 456 bpfjit_func_t code; 457 uint8_t pkt[1] = { 0 }; 458 bpf_args_t args = { 459 .pkt = pkt, 460 .buflen = sizeof(pkt), 461 .wirelen = sizeof(pkt), 462 }; 463 464 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 465 466 RZ(rump_init()); 467 468 rump_schedule(); 469 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 470 rump_unschedule(); 471 ATF_REQUIRE(code != NULL); 472 473 ATF_CHECK(code(&ctx, &args) == 13); 474 475 rump_schedule(); 476 rumpns_bpfjit_free_code(code); 477 rump_unschedule(); 478} 479 480ATF_TC(bpfjit_copx_ret_buflen); 481ATF_TC_HEAD(bpfjit_copx_ret_buflen, tc) 482{ 483 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 484 "that returns the buflen argument"); 485} 486 487ATF_TC_BODY(bpfjit_copx_ret_buflen, tc) 488{ 489 static struct bpf_insn insns[] = { 490 BPF_STMT(BPF_LD+BPF_IMM, 13), 491 BPF_STMT(BPF_LDX+BPF_IMM, 1), // retBL 492 BPF_STMT(BPF_MISC+BPF_COPX, 0), 493 BPF_STMT(BPF_RET+BPF_A, 0) 494 }; 495 496 bpfjit_func_t code; 497 uint8_t pkt[1] = { 0 }; 498 bpf_args_t args = { 499 .pkt = pkt, 500 .buflen = sizeof(pkt), 501 .wirelen = sizeof(pkt) 502 }; 503 504 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 505 506 RZ(rump_init()); 507 508 rump_schedule(); 509 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 510 rump_unschedule(); 511 ATF_REQUIRE(code != NULL); 512 513 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 514 515 rump_schedule(); 516 rumpns_bpfjit_free_code(code); 517 rump_unschedule(); 518} 519 520ATF_TC(bpfjit_copx_ret_wirelen); 521ATF_TC_HEAD(bpfjit_copx_ret_wirelen, tc) 522{ 523 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 524 "that returns the wirelen argument"); 525} 526 527ATF_TC_BODY(bpfjit_copx_ret_wirelen, tc) 528{ 529 static struct bpf_insn insns[] = { 530 BPF_STMT(BPF_LDX+BPF_IMM, 2), // retWL 531 BPF_STMT(BPF_LD+BPF_IMM, 13), 532 BPF_STMT(BPF_MISC+BPF_COPX, 0), 533 BPF_STMT(BPF_RET+BPF_A, 0) 534 }; 535 536 bpfjit_func_t code; 537 uint8_t pkt[1] = { 0 }; 538 bpf_args_t args = { 539 .pkt = pkt, 540 .buflen = sizeof(pkt), 541 .wirelen = sizeof(pkt) 542 }; 543 544 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 545 546 RZ(rump_init()); 547 548 rump_schedule(); 549 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 550 rump_unschedule(); 551 ATF_REQUIRE(code != NULL); 552 553 ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 554 555 rump_schedule(); 556 rumpns_bpfjit_free_code(code); 557 rump_unschedule(); 558} 559 560ATF_TC(bpfjit_copx_ret_nfuncs); 561ATF_TC_HEAD(bpfjit_copx_ret_nfuncs, tc) 562{ 563 atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 564 "that returns nfuncs member of the context argument"); 565} 566 567ATF_TC_BODY(bpfjit_copx_ret_nfuncs, tc) 568{ 569 static struct bpf_insn insns[] = { 570 BPF_STMT(BPF_LD+BPF_IMM, 13), 571 BPF_STMT(BPF_LDX+BPF_IMM, 3), // retNF 572 BPF_STMT(BPF_MISC+BPF_COPX, 0), 573 BPF_STMT(BPF_RET+BPF_A, 0) 574 }; 575 576 bpfjit_func_t code; 577 uint8_t pkt[1] = { 0 }; 578 bpf_args_t args = { 579 .pkt = pkt, 580 .buflen = sizeof(pkt), 581 .wirelen = sizeof(pkt) 582 }; 583 584 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 585 586 RZ(rump_init()); 587 588 rump_schedule(); 589 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 590 rump_unschedule(); 591 ATF_REQUIRE(code != NULL); 592 593 ATF_CHECK(code(&ctx, &args) == ctx.nfuncs); 594 595 rump_schedule(); 596 rumpns_bpfjit_free_code(code); 597 rump_unschedule(); 598} 599 600ATF_TC(bpfjit_copx_side_effect); 601ATF_TC_HEAD(bpfjit_copx_side_effect, tc) 602{ 603 atf_tc_set_md_var(tc, "descr", 604 "Test that ABC optimization doesn't skip BPF_COPX call"); 605} 606 607ATF_TC_BODY(bpfjit_copx_side_effect, tc) 608{ 609 static struct bpf_insn insns[] = { 610 BPF_STMT(BPF_LD+BPF_IMM, 13), 611 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), 612 BPF_STMT(BPF_LDX+BPF_IMM, 4), // setARG 613 BPF_STMT(BPF_MISC+BPF_COPX, 0), 614 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999), 615 BPF_STMT(BPF_RET+BPF_A, 0) 616 }; 617 618 bpfjit_func_t code; 619 bool arg = false; 620 uint8_t pkt[1] = { 0 }; 621 bpf_args_t args = { 622 .pkt = pkt, 623 .buflen = sizeof(pkt), 624 .wirelen = sizeof(pkt), 625 .mem = NULL, 626 .arg = &arg 627 }; 628 629 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 630 631 RZ(rump_init()); 632 633 rump_schedule(); 634 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 635 rump_unschedule(); 636 ATF_REQUIRE(code != NULL); 637 638 ATF_CHECK(code(&ctx, &args) == 0); 639 ATF_CHECK(arg == true); 640 641 rump_schedule(); 642 rumpns_bpfjit_free_code(code); 643 rump_unschedule(); 644} 645 646ATF_TC(bpfjit_copx_cop); 647ATF_TC_HEAD(bpfjit_copx_cop, tc) 648{ 649 atf_tc_set_md_var(tc, "descr", 650 "Test BPF_COPX call followed by BPF_COP call"); 651} 652 653ATF_TC_BODY(bpfjit_copx_cop, tc) 654{ 655 static struct bpf_insn insns[] = { 656 BPF_STMT(BPF_LDX+BPF_IMM, 2), /* X <- 2 */ 657 BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retWL */ 658 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 659 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 660 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */ 661 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 662 BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 663 BPF_STMT(BPF_MISC+BPF_COP, 3), /* retNF */ 664 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 665 BPF_STMT(BPF_RET+BPF_A, 0) 666 }; 667 668 bpfjit_func_t code; 669 uint8_t pkt[1] = { 2 }; 670 bpf_args_t args = { 671 .pkt = pkt, 672 .buflen = sizeof(pkt), 673 .wirelen = sizeof(pkt), 674 }; 675 676 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 677 678 RZ(rump_init()); 679 680 rump_schedule(); 681 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 682 rump_unschedule(); 683 ATF_REQUIRE(code != NULL); 684 685 ATF_CHECK(code(&ctx, &args) == 5 + ctx.nfuncs); 686 687 rump_schedule(); 688 rumpns_bpfjit_free_code(code); 689 rump_unschedule(); 690} 691 692ATF_TC(bpfjit_copx_invalid_index); 693ATF_TC_HEAD(bpfjit_copx_invalid_index, tc) 694{ 695 atf_tc_set_md_var(tc, "descr", 696 "Test that out-of-range BPF_COPX call fails at runtime"); 697} 698 699ATF_TC_BODY(bpfjit_copx_invalid_index, tc) 700{ 701 static struct bpf_insn insns[] = { 702 BPF_STMT(BPF_LDX+BPF_IMM, 5), // invalid index 703 BPF_STMT(BPF_MISC+BPF_COPX, 0), 704 BPF_STMT(BPF_RET+BPF_K, 27) 705 }; 706 707 bpfjit_func_t code; 708 uint8_t pkt[1] = { 0 }; 709 bpf_args_t args = { 710 .pkt = pkt, 711 .buflen = sizeof(pkt), 712 .wirelen = sizeof(pkt) 713 }; 714 715 size_t insn_count = sizeof(insns) / sizeof(insns[0]); 716 717 RZ(rump_init()); 718 719 rump_schedule(); 720 code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count); 721 rump_unschedule(); 722 ATF_REQUIRE(code != NULL); 723 724 ATF_CHECK(code(&ctx, &args) == 0); 725 726 rump_schedule(); 727 rumpns_bpfjit_free_code(code); 728 rump_unschedule(); 729} 730 731ATF_TP_ADD_TCS(tp) 732{ 733 734 /* 735 * For every new test please also add a similar test 736 * to ../../lib/libbpfjit/t_cop.c 737 */ 738 ATF_TP_ADD_TC(tp, bpfjit_cop_no_ctx); 739 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_A); 740 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_buflen); 741 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_wirelen); 742 ATF_TP_ADD_TC(tp, bpfjit_cop_ret_nfuncs); 743 ATF_TP_ADD_TC(tp, bpfjit_cop_side_effect); 744 ATF_TP_ADD_TC(tp, bpfjit_cop_copx); 745 ATF_TP_ADD_TC(tp, bpfjit_cop_invalid_index); 746 747 ATF_TP_ADD_TC(tp, bpfjit_copx_no_ctx); 748 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_A); 749 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_buflen); 750 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_wirelen); 751 ATF_TP_ADD_TC(tp, bpfjit_copx_ret_nfuncs); 752 ATF_TP_ADD_TC(tp, bpfjit_copx_side_effect); 753 ATF_TP_ADD_TC(tp, bpfjit_copx_cop); 754 ATF_TP_ADD_TC(tp, bpfjit_copx_invalid_index); 755 756 return atf_no_error(); 757} 758