1// SPDX-License-Identifier: GPL-2.0 2/* Converted from tools/testing/selftests/bpf/verifier/direct_packet_access.c */ 3 4#include <linux/bpf.h> 5#include <bpf/bpf_helpers.h> 6#include "bpf_misc.h" 7 8SEC("tc") 9__description("pkt_end - pkt_start is allowed") 10__success __retval(TEST_DATA_LEN) 11__naked void end_pkt_start_is_allowed(void) 12{ 13 asm volatile (" \ 14 r0 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 15 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 16 r0 -= r2; \ 17 exit; \ 18" : 19 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 20 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 21 : __clobber_all); 22} 23 24SEC("tc") 25__description("direct packet access: test1") 26__success __retval(0) 27__naked void direct_packet_access_test1(void) 28{ 29 asm volatile (" \ 30 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 31 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 32 r0 = r2; \ 33 r0 += 8; \ 34 if r0 > r3 goto l0_%=; \ 35 r0 = *(u8*)(r2 + 0); \ 36l0_%=: r0 = 0; \ 37 exit; \ 38" : 39 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 40 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 41 : __clobber_all); 42} 43 44SEC("tc") 45__description("direct packet access: test2") 46__success __retval(0) 47__naked void direct_packet_access_test2(void) 48{ 49 asm volatile (" \ 50 r0 = 1; \ 51 r4 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 52 r3 = *(u32*)(r1 + %[__sk_buff_data]); \ 53 r5 = r3; \ 54 r5 += 14; \ 55 if r5 > r4 goto l0_%=; \ 56 r0 = *(u8*)(r3 + 7); \ 57 r4 = *(u8*)(r3 + 12); \ 58 r4 *= 14; \ 59 r3 = *(u32*)(r1 + %[__sk_buff_data]); \ 60 r3 += r4; \ 61 r2 = *(u32*)(r1 + %[__sk_buff_len]); \ 62 r2 <<= 49; \ 63 r2 >>= 49; \ 64 r3 += r2; \ 65 r2 = r3; \ 66 r2 += 8; \ 67 r1 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 68 if r2 > r1 goto l1_%=; \ 69 r1 = *(u8*)(r3 + 4); \ 70l1_%=: r0 = 0; \ 71l0_%=: exit; \ 72" : 73 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 74 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)), 75 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 76 : __clobber_all); 77} 78 79SEC("socket") 80__description("direct packet access: test3") 81__failure __msg("invalid bpf_context access off=76") 82__failure_unpriv 83__naked void direct_packet_access_test3(void) 84{ 85 asm volatile (" \ 86 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 87 r0 = 0; \ 88 exit; \ 89" : 90 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)) 91 : __clobber_all); 92} 93 94SEC("tc") 95__description("direct packet access: test4 (write)") 96__success __retval(0) 97__naked void direct_packet_access_test4_write(void) 98{ 99 asm volatile (" \ 100 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 101 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 102 r0 = r2; \ 103 r0 += 8; \ 104 if r0 > r3 goto l0_%=; \ 105 *(u8*)(r2 + 0) = r2; \ 106l0_%=: r0 = 0; \ 107 exit; \ 108" : 109 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 110 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 111 : __clobber_all); 112} 113 114SEC("tc") 115__description("direct packet access: test5 (pkt_end >= reg, good access)") 116__success __retval(0) 117__naked void pkt_end_reg_good_access(void) 118{ 119 asm volatile (" \ 120 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 121 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 122 r0 = r2; \ 123 r0 += 8; \ 124 if r3 >= r0 goto l0_%=; \ 125 r0 = 1; \ 126 exit; \ 127l0_%=: r0 = *(u8*)(r2 + 0); \ 128 r0 = 0; \ 129 exit; \ 130" : 131 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 132 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 133 : __clobber_all); 134} 135 136SEC("tc") 137__description("direct packet access: test6 (pkt_end >= reg, bad access)") 138__failure __msg("invalid access to packet") 139__naked void pkt_end_reg_bad_access(void) 140{ 141 asm volatile (" \ 142 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 143 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 144 r0 = r2; \ 145 r0 += 8; \ 146 if r3 >= r0 goto l0_%=; \ 147 r0 = *(u8*)(r2 + 0); \ 148 r0 = 1; \ 149 exit; \ 150l0_%=: r0 = 0; \ 151 exit; \ 152" : 153 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 154 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 155 : __clobber_all); 156} 157 158SEC("tc") 159__description("direct packet access: test7 (pkt_end >= reg, both accesses)") 160__failure __msg("invalid access to packet") 161__naked void pkt_end_reg_both_accesses(void) 162{ 163 asm volatile (" \ 164 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 165 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 166 r0 = r2; \ 167 r0 += 8; \ 168 if r3 >= r0 goto l0_%=; \ 169 r0 = *(u8*)(r2 + 0); \ 170 r0 = 1; \ 171 exit; \ 172l0_%=: r0 = *(u8*)(r2 + 0); \ 173 r0 = 0; \ 174 exit; \ 175" : 176 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 177 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 178 : __clobber_all); 179} 180 181SEC("tc") 182__description("direct packet access: test8 (double test, variant 1)") 183__success __retval(0) 184__naked void test8_double_test_variant_1(void) 185{ 186 asm volatile (" \ 187 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 188 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 189 r0 = r2; \ 190 r0 += 8; \ 191 if r3 >= r0 goto l0_%=; \ 192 if r0 > r3 goto l1_%=; \ 193 r0 = *(u8*)(r2 + 0); \ 194l1_%=: r0 = 1; \ 195 exit; \ 196l0_%=: r0 = *(u8*)(r2 + 0); \ 197 r0 = 0; \ 198 exit; \ 199" : 200 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 201 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 202 : __clobber_all); 203} 204 205SEC("tc") 206__description("direct packet access: test9 (double test, variant 2)") 207__success __retval(0) 208__naked void test9_double_test_variant_2(void) 209{ 210 asm volatile (" \ 211 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 212 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 213 r0 = r2; \ 214 r0 += 8; \ 215 if r3 >= r0 goto l0_%=; \ 216 r0 = 1; \ 217 exit; \ 218l0_%=: if r0 > r3 goto l1_%=; \ 219 r0 = *(u8*)(r2 + 0); \ 220l1_%=: r0 = *(u8*)(r2 + 0); \ 221 r0 = 0; \ 222 exit; \ 223" : 224 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 225 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 226 : __clobber_all); 227} 228 229SEC("tc") 230__description("direct packet access: test10 (write invalid)") 231__failure __msg("invalid access to packet") 232__naked void packet_access_test10_write_invalid(void) 233{ 234 asm volatile (" \ 235 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 236 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 237 r0 = r2; \ 238 r0 += 8; \ 239 if r0 > r3 goto l0_%=; \ 240 r0 = 0; \ 241 exit; \ 242l0_%=: *(u8*)(r2 + 0) = r2; \ 243 r0 = 0; \ 244 exit; \ 245" : 246 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 247 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 248 : __clobber_all); 249} 250 251SEC("tc") 252__description("direct packet access: test11 (shift, good access)") 253__success __retval(1) 254__naked void access_test11_shift_good_access(void) 255{ 256 asm volatile (" \ 257 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 258 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 259 r0 = r2; \ 260 r0 += 22; \ 261 if r0 > r3 goto l0_%=; \ 262 r3 = 144; \ 263 r5 = r3; \ 264 r5 += 23; \ 265 r5 >>= 3; \ 266 r6 = r2; \ 267 r6 += r5; \ 268 r0 = 1; \ 269 exit; \ 270l0_%=: r0 = 0; \ 271 exit; \ 272" : 273 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 274 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 275 : __clobber_all); 276} 277 278SEC("tc") 279__description("direct packet access: test12 (and, good access)") 280__success __retval(1) 281__naked void access_test12_and_good_access(void) 282{ 283 asm volatile (" \ 284 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 285 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 286 r0 = r2; \ 287 r0 += 22; \ 288 if r0 > r3 goto l0_%=; \ 289 r3 = 144; \ 290 r5 = r3; \ 291 r5 += 23; \ 292 r5 &= 15; \ 293 r6 = r2; \ 294 r6 += r5; \ 295 r0 = 1; \ 296 exit; \ 297l0_%=: r0 = 0; \ 298 exit; \ 299" : 300 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 301 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 302 : __clobber_all); 303} 304 305SEC("tc") 306__description("direct packet access: test13 (branches, good access)") 307__success __retval(1) 308__naked void access_test13_branches_good_access(void) 309{ 310 asm volatile (" \ 311 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 312 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 313 r0 = r2; \ 314 r0 += 22; \ 315 if r0 > r3 goto l0_%=; \ 316 r3 = *(u32*)(r1 + %[__sk_buff_mark]); \ 317 r4 = 1; \ 318 if r3 > r4 goto l1_%=; \ 319 r3 = 14; \ 320 goto l2_%=; \ 321l1_%=: r3 = 24; \ 322l2_%=: r5 = r3; \ 323 r5 += 23; \ 324 r5 &= 15; \ 325 r6 = r2; \ 326 r6 += r5; \ 327 r0 = 1; \ 328 exit; \ 329l0_%=: r0 = 0; \ 330 exit; \ 331" : 332 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 333 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)), 334 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 335 : __clobber_all); 336} 337 338SEC("tc") 339__description("direct packet access: test14 (pkt_ptr += 0, CONST_IMM, good access)") 340__success __retval(1) 341__naked void _0_const_imm_good_access(void) 342{ 343 asm volatile (" \ 344 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 345 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 346 r0 = r2; \ 347 r0 += 22; \ 348 if r0 > r3 goto l0_%=; \ 349 r5 = 12; \ 350 r5 >>= 4; \ 351 r6 = r2; \ 352 r6 += r5; \ 353 r0 = *(u8*)(r6 + 0); \ 354 r0 = 1; \ 355 exit; \ 356l0_%=: r0 = 0; \ 357 exit; \ 358" : 359 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 360 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 361 : __clobber_all); 362} 363 364SEC("tc") 365__description("direct packet access: test15 (spill with xadd)") 366__failure __msg("R2 invalid mem access 'scalar'") 367__flag(BPF_F_ANY_ALIGNMENT) 368__naked void access_test15_spill_with_xadd(void) 369{ 370 asm volatile (" \ 371 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 372 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 373 r0 = r2; \ 374 r0 += 8; \ 375 if r0 > r3 goto l0_%=; \ 376 r5 = 4096; \ 377 r4 = r10; \ 378 r4 += -8; \ 379 *(u64*)(r4 + 0) = r2; \ 380 lock *(u64 *)(r4 + 0) += r5; \ 381 r2 = *(u64*)(r4 + 0); \ 382 *(u32*)(r2 + 0) = r5; \ 383 r0 = 0; \ 384l0_%=: exit; \ 385" : 386 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 387 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 388 : __clobber_all); 389} 390 391SEC("tc") 392__description("direct packet access: test16 (arith on data_end)") 393__failure __msg("R3 pointer arithmetic on pkt_end") 394__naked void test16_arith_on_data_end(void) 395{ 396 asm volatile (" \ 397 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 398 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 399 r0 = r2; \ 400 r0 += 8; \ 401 r3 += 16; \ 402 if r0 > r3 goto l0_%=; \ 403 *(u8*)(r2 + 0) = r2; \ 404l0_%=: r0 = 0; \ 405 exit; \ 406" : 407 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 408 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 409 : __clobber_all); 410} 411 412SEC("tc") 413__description("direct packet access: test17 (pruning, alignment)") 414__failure __msg("misaligned packet access off 2+0+15+-4 size 4") 415__flag(BPF_F_STRICT_ALIGNMENT) 416__naked void packet_access_test17_pruning_alignment(void) 417{ 418 asm volatile (" \ 419 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 420 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 421 r7 = *(u32*)(r1 + %[__sk_buff_mark]); \ 422 r0 = r2; \ 423 r0 += 14; \ 424 if r7 > 1 goto l0_%=; \ 425l2_%=: if r0 > r3 goto l1_%=; \ 426 *(u32*)(r0 - 4) = r0; \ 427l1_%=: r0 = 0; \ 428 exit; \ 429l0_%=: r0 += 1; \ 430 goto l2_%=; \ 431" : 432 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 433 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)), 434 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 435 : __clobber_all); 436} 437 438SEC("tc") 439__description("direct packet access: test18 (imm += pkt_ptr, 1)") 440__success __retval(0) 441__naked void test18_imm_pkt_ptr_1(void) 442{ 443 asm volatile (" \ 444 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 445 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 446 r0 = 8; \ 447 r0 += r2; \ 448 if r0 > r3 goto l0_%=; \ 449 *(u8*)(r2 + 0) = r2; \ 450l0_%=: r0 = 0; \ 451 exit; \ 452" : 453 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 454 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 455 : __clobber_all); 456} 457 458SEC("tc") 459__description("direct packet access: test19 (imm += pkt_ptr, 2)") 460__success __retval(0) 461__naked void test19_imm_pkt_ptr_2(void) 462{ 463 asm volatile (" \ 464 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 465 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 466 r0 = r2; \ 467 r0 += 8; \ 468 if r0 > r3 goto l0_%=; \ 469 r4 = 4; \ 470 r4 += r2; \ 471 *(u8*)(r4 + 0) = r4; \ 472l0_%=: r0 = 0; \ 473 exit; \ 474" : 475 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 476 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 477 : __clobber_all); 478} 479 480SEC("tc") 481__description("direct packet access: test20 (x += pkt_ptr, 1)") 482__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 483__naked void test20_x_pkt_ptr_1(void) 484{ 485 asm volatile (" \ 486 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 487 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 488 r0 = 0xffffffff; \ 489 *(u64*)(r10 - 8) = r0; \ 490 r0 = *(u64*)(r10 - 8); \ 491 r0 &= 0x7fff; \ 492 r4 = r0; \ 493 r4 += r2; \ 494 r5 = r4; \ 495 r4 += %[__imm_0]; \ 496 if r4 > r3 goto l0_%=; \ 497 *(u64*)(r5 + 0) = r4; \ 498l0_%=: r0 = 0; \ 499 exit; \ 500" : 501 : __imm_const(__imm_0, 0x7fff - 1), 502 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 503 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 504 : __clobber_all); 505} 506 507SEC("tc") 508__description("direct packet access: test21 (x += pkt_ptr, 2)") 509__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 510__naked void test21_x_pkt_ptr_2(void) 511{ 512 asm volatile (" \ 513 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 514 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 515 r0 = r2; \ 516 r0 += 8; \ 517 if r0 > r3 goto l0_%=; \ 518 r4 = 0xffffffff; \ 519 *(u64*)(r10 - 8) = r4; \ 520 r4 = *(u64*)(r10 - 8); \ 521 r4 &= 0x7fff; \ 522 r4 += r2; \ 523 r5 = r4; \ 524 r4 += %[__imm_0]; \ 525 if r4 > r3 goto l0_%=; \ 526 *(u64*)(r5 + 0) = r4; \ 527l0_%=: r0 = 0; \ 528 exit; \ 529" : 530 : __imm_const(__imm_0, 0x7fff - 1), 531 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 532 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 533 : __clobber_all); 534} 535 536SEC("tc") 537__description("direct packet access: test22 (x += pkt_ptr, 3)") 538__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 539__naked void test22_x_pkt_ptr_3(void) 540{ 541 asm volatile (" \ 542 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 543 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 544 r0 = r2; \ 545 r0 += 8; \ 546 *(u64*)(r10 - 8) = r2; \ 547 *(u64*)(r10 - 16) = r3; \ 548 r3 = *(u64*)(r10 - 16); \ 549 if r0 > r3 goto l0_%=; \ 550 r2 = *(u64*)(r10 - 8); \ 551 r4 = 0xffffffff; \ 552 lock *(u64 *)(r10 - 8) += r4; \ 553 r4 = *(u64*)(r10 - 8); \ 554 r4 >>= 49; \ 555 r4 += r2; \ 556 r0 = r4; \ 557 r0 += 2; \ 558 if r0 > r3 goto l0_%=; \ 559 r2 = 1; \ 560 *(u16*)(r4 + 0) = r2; \ 561l0_%=: r0 = 0; \ 562 exit; \ 563" : 564 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 565 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 566 : __clobber_all); 567} 568 569SEC("tc") 570__description("direct packet access: test23 (x += pkt_ptr, 4)") 571__failure __msg("invalid access to packet, off=0 size=8, R5(id=3,off=0,r=0)") 572__flag(BPF_F_ANY_ALIGNMENT) 573__naked void test23_x_pkt_ptr_4(void) 574{ 575 asm volatile (" \ 576 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 577 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 578 r0 = *(u32*)(r1 + %[__sk_buff_mark]); \ 579 *(u64*)(r10 - 8) = r0; \ 580 r0 = *(u64*)(r10 - 8); \ 581 r0 &= 0xffff; \ 582 r4 = r0; \ 583 r0 = 31; \ 584 r0 += r4; \ 585 r0 += r2; \ 586 r5 = r0; \ 587 r0 += %[__imm_0]; \ 588 if r0 > r3 goto l0_%=; \ 589 *(u64*)(r5 + 0) = r0; \ 590l0_%=: r0 = 0; \ 591 exit; \ 592" : 593 : __imm_const(__imm_0, 0xffff - 1), 594 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 595 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)), 596 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 597 : __clobber_all); 598} 599 600SEC("tc") 601__description("direct packet access: test24 (x += pkt_ptr, 5)") 602__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 603__naked void test24_x_pkt_ptr_5(void) 604{ 605 asm volatile (" \ 606 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 607 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 608 r0 = 0xffffffff; \ 609 *(u64*)(r10 - 8) = r0; \ 610 r0 = *(u64*)(r10 - 8); \ 611 r0 &= 0xff; \ 612 r4 = r0; \ 613 r0 = 64; \ 614 r0 += r4; \ 615 r0 += r2; \ 616 r5 = r0; \ 617 r0 += %[__imm_0]; \ 618 if r0 > r3 goto l0_%=; \ 619 *(u64*)(r5 + 0) = r0; \ 620l0_%=: r0 = 0; \ 621 exit; \ 622" : 623 : __imm_const(__imm_0, 0x7fff - 1), 624 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 625 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 626 : __clobber_all); 627} 628 629SEC("tc") 630__description("direct packet access: test25 (marking on <, good access)") 631__success __retval(0) 632__naked void test25_marking_on_good_access(void) 633{ 634 asm volatile (" \ 635 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 636 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 637 r0 = r2; \ 638 r0 += 8; \ 639 if r0 < r3 goto l0_%=; \ 640l1_%=: r0 = 0; \ 641 exit; \ 642l0_%=: r0 = *(u8*)(r2 + 0); \ 643 goto l1_%=; \ 644" : 645 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 646 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 647 : __clobber_all); 648} 649 650SEC("tc") 651__description("direct packet access: test26 (marking on <, bad access)") 652__failure __msg("invalid access to packet") 653__naked void test26_marking_on_bad_access(void) 654{ 655 asm volatile (" \ 656 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 657 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 658 r0 = r2; \ 659 r0 += 8; \ 660 if r0 < r3 goto l0_%=; \ 661 r0 = *(u8*)(r2 + 0); \ 662l1_%=: r0 = 0; \ 663 exit; \ 664l0_%=: goto l1_%=; \ 665" : 666 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 667 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 668 : __clobber_all); 669} 670 671SEC("tc") 672__description("direct packet access: test27 (marking on <=, good access)") 673__success __retval(1) 674__naked void test27_marking_on_good_access(void) 675{ 676 asm volatile (" \ 677 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 678 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 679 r0 = r2; \ 680 r0 += 8; \ 681 if r3 <= r0 goto l0_%=; \ 682 r0 = *(u8*)(r2 + 0); \ 683l0_%=: r0 = 1; \ 684 exit; \ 685" : 686 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 687 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 688 : __clobber_all); 689} 690 691SEC("tc") 692__description("direct packet access: test28 (marking on <=, bad access)") 693__failure __msg("invalid access to packet") 694__naked void test28_marking_on_bad_access(void) 695{ 696 asm volatile (" \ 697 r2 = *(u32*)(r1 + %[__sk_buff_data]); \ 698 r3 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 699 r0 = r2; \ 700 r0 += 8; \ 701 if r3 <= r0 goto l0_%=; \ 702l1_%=: r0 = 1; \ 703 exit; \ 704l0_%=: r0 = *(u8*)(r2 + 0); \ 705 goto l1_%=; \ 706" : 707 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 708 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 709 : __clobber_all); 710} 711 712SEC("tc") 713__description("direct packet access: test29 (reg > pkt_end in subprog)") 714__success __retval(0) 715__naked void reg_pkt_end_in_subprog(void) 716{ 717 asm volatile (" \ 718 r6 = *(u32*)(r1 + %[__sk_buff_data]); \ 719 r2 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 720 r3 = r6; \ 721 r3 += 8; \ 722 call reg_pkt_end_in_subprog__1; \ 723 if r0 == 0 goto l0_%=; \ 724 r0 = *(u8*)(r6 + 0); \ 725l0_%=: r0 = 0; \ 726 exit; \ 727" : 728 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 729 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 730 : __clobber_all); 731} 732 733static __naked __noinline __attribute__((used)) 734void reg_pkt_end_in_subprog__1(void) 735{ 736 asm volatile (" \ 737 r0 = 0; \ 738 if r3 > r2 goto l0_%=; \ 739 r0 = 1; \ 740l0_%=: exit; \ 741" ::: __clobber_all); 742} 743 744SEC("tc") 745__description("direct packet access: test30 (check_id() in regsafe(), bad access)") 746__failure __msg("invalid access to packet, off=0 size=1, R2") 747__flag(BPF_F_TEST_STATE_FREQ) 748__naked void id_in_regsafe_bad_access(void) 749{ 750 asm volatile (" \ 751 /* r9 = ctx */ \ 752 r9 = r1; \ 753 /* r7 = ktime_get_ns() */ \ 754 call %[bpf_ktime_get_ns]; \ 755 r7 = r0; \ 756 /* r6 = ktime_get_ns() */ \ 757 call %[bpf_ktime_get_ns]; \ 758 r6 = r0; \ 759 /* r2 = ctx->data \ 760 * r3 = ctx->data \ 761 * r4 = ctx->data_end \ 762 */ \ 763 r2 = *(u32*)(r9 + %[__sk_buff_data]); \ 764 r3 = *(u32*)(r9 + %[__sk_buff_data]); \ 765 r4 = *(u32*)(r9 + %[__sk_buff_data_end]); \ 766 /* if r6 > 100 goto exit \ 767 * if r7 > 100 goto exit \ 768 */ \ 769 if r6 > 100 goto l0_%=; \ 770 if r7 > 100 goto l0_%=; \ 771 /* r2 += r6 ; this forces assignment of ID to r2\ 772 * r2 += 1 ; get some fixed off for r2\ 773 * r3 += r7 ; this forces assignment of ID to r3\ 774 * r3 += 1 ; get some fixed off for r3\ 775 */ \ 776 r2 += r6; \ 777 r2 += 1; \ 778 r3 += r7; \ 779 r3 += 1; \ 780 /* if r6 > r7 goto +1 ; no new information about the state is derived from\ 781 * ; this check, thus produced verifier states differ\ 782 * ; only in 'insn_idx' \ 783 * r2 = r3 ; optionally share ID between r2 and r3\ 784 */ \ 785 if r6 != r7 goto l1_%=; \ 786 r2 = r3; \ 787l1_%=: /* if r3 > ctx->data_end goto exit */ \ 788 if r3 > r4 goto l0_%=; \ 789 /* r5 = *(u8 *) (r2 - 1) ; access packet memory using r2,\ 790 * ; this is not always safe\ 791 */ \ 792 r5 = *(u8*)(r2 - 1); \ 793l0_%=: /* exit(0) */ \ 794 r0 = 0; \ 795 exit; \ 796" : 797 : __imm(bpf_ktime_get_ns), 798 __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 799 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 800 : __clobber_all); 801} 802 803char _license[] SEC("license") = "GPL"; 804