Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 611 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2#include <vmlinux.h> 3#include <bpf/bpf_tracing.h> 4#include <bpf/bpf_helpers.h> 5#include <bpf/bpf_core_read.h> 6#include "bpf_experimental.h" 7 8#include "linked_list.h" 9 10#define INIT \ 11 struct map_value *v, *v2, *iv, *iv2; \ 12 struct foo *f, *f1, *f2; \ 13 struct bar *b; \ 14 void *map; \ 15 \ 16 map = bpf_map_lookup_elem(&map_of_maps, &(int){ 0 }); \ 17 if (!map) \ 18 return 0; \ 19 v = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \ 20 if (!v) \ 21 return 0; \ 22 v2 = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \ 23 if (!v2) \ 24 return 0; \ 25 iv = bpf_map_lookup_elem(map, &(int){ 0 }); \ 26 if (!iv) \ 27 return 0; \ 28 iv2 = bpf_map_lookup_elem(map, &(int){ 0 }); \ 29 if (!iv2) \ 30 return 0; \ 31 f = bpf_obj_new(typeof(*f)); \ 32 if (!f) \ 33 return 0; \ 34 f1 = f; \ 35 f2 = bpf_obj_new(typeof(*f2)); \ 36 if (!f2) { \ 37 bpf_obj_drop(f1); \ 38 return 0; \ 39 } \ 40 b = bpf_obj_new(typeof(*b)); \ 41 if (!b) { \ 42 bpf_obj_drop(f2); \ 43 bpf_obj_drop(f1); \ 44 return 0; \ 45 } 46 47#define CHECK(test, op, hexpr) \ 48 SEC("?tc") \ 49 int test##_missing_lock_##op(void *ctx) \ 50 { \ 51 INIT; \ 52 void (*p)(void *) = (void *)&bpf_list_##op; \ 53 p(hexpr); \ 54 return 0; \ 55 } 56 57CHECK(kptr, pop_front, &f->head); 58CHECK(kptr, pop_back, &f->head); 59 60CHECK(global, pop_front, &ghead); 61CHECK(global, pop_back, &ghead); 62 63CHECK(map, pop_front, &v->head); 64CHECK(map, pop_back, &v->head); 65 66CHECK(inner_map, pop_front, &iv->head); 67CHECK(inner_map, pop_back, &iv->head); 68 69#undef CHECK 70 71#define CHECK(test, op, hexpr, nexpr) \ 72 SEC("?tc") \ 73 int test##_missing_lock_##op(void *ctx) \ 74 { \ 75 INIT; \ 76 bpf_list_##op(hexpr, nexpr); \ 77 return 0; \ 78 } 79 80CHECK(kptr, push_front, &f->head, &b->node); 81CHECK(kptr, push_back, &f->head, &b->node); 82 83CHECK(global, push_front, &ghead, &f->node2); 84CHECK(global, push_back, &ghead, &f->node2); 85 86CHECK(map, push_front, &v->head, &f->node2); 87CHECK(map, push_back, &v->head, &f->node2); 88 89CHECK(inner_map, push_front, &iv->head, &f->node2); 90CHECK(inner_map, push_back, &iv->head, &f->node2); 91 92#undef CHECK 93 94#define CHECK(test, op, lexpr, hexpr) \ 95 SEC("?tc") \ 96 int test##_incorrect_lock_##op(void *ctx) \ 97 { \ 98 INIT; \ 99 void (*p)(void *) = (void *)&bpf_list_##op; \ 100 bpf_spin_lock(lexpr); \ 101 p(hexpr); \ 102 return 0; \ 103 } 104 105#define CHECK_OP(op) \ 106 CHECK(kptr_kptr, op, &f1->lock, &f2->head); \ 107 CHECK(kptr_global, op, &f1->lock, &ghead); \ 108 CHECK(kptr_map, op, &f1->lock, &v->head); \ 109 CHECK(kptr_inner_map, op, &f1->lock, &iv->head); \ 110 \ 111 CHECK(global_global, op, &glock2, &ghead); \ 112 CHECK(global_kptr, op, &glock, &f1->head); \ 113 CHECK(global_map, op, &glock, &v->head); \ 114 CHECK(global_inner_map, op, &glock, &iv->head); \ 115 \ 116 CHECK(map_map, op, &v->lock, &v2->head); \ 117 CHECK(map_kptr, op, &v->lock, &f2->head); \ 118 CHECK(map_global, op, &v->lock, &ghead); \ 119 CHECK(map_inner_map, op, &v->lock, &iv->head); \ 120 \ 121 CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head); \ 122 CHECK(inner_map_kptr, op, &iv->lock, &f2->head); \ 123 CHECK(inner_map_global, op, &iv->lock, &ghead); \ 124 CHECK(inner_map_map, op, &iv->lock, &v->head); 125 126CHECK_OP(pop_front); 127CHECK_OP(pop_back); 128 129#undef CHECK 130#undef CHECK_OP 131 132#define CHECK(test, op, lexpr, hexpr, nexpr) \ 133 SEC("?tc") \ 134 int test##_incorrect_lock_##op(void *ctx) \ 135 { \ 136 INIT; \ 137 bpf_spin_lock(lexpr); \ 138 bpf_list_##op(hexpr, nexpr); \ 139 return 0; \ 140 } 141 142#define CHECK_OP(op) \ 143 CHECK(kptr_kptr, op, &f1->lock, &f2->head, &b->node); \ 144 CHECK(kptr_global, op, &f1->lock, &ghead, &f->node2); \ 145 CHECK(kptr_map, op, &f1->lock, &v->head, &f->node2); \ 146 CHECK(kptr_inner_map, op, &f1->lock, &iv->head, &f->node2); \ 147 \ 148 CHECK(global_global, op, &glock2, &ghead, &f->node2); \ 149 CHECK(global_kptr, op, &glock, &f1->head, &b->node); \ 150 CHECK(global_map, op, &glock, &v->head, &f->node2); \ 151 CHECK(global_inner_map, op, &glock, &iv->head, &f->node2); \ 152 \ 153 CHECK(map_map, op, &v->lock, &v2->head, &f->node2); \ 154 CHECK(map_kptr, op, &v->lock, &f2->head, &b->node); \ 155 CHECK(map_global, op, &v->lock, &ghead, &f->node2); \ 156 CHECK(map_inner_map, op, &v->lock, &iv->head, &f->node2); \ 157 \ 158 CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head, &f->node2);\ 159 CHECK(inner_map_kptr, op, &iv->lock, &f2->head, &b->node); \ 160 CHECK(inner_map_global, op, &iv->lock, &ghead, &f->node2); \ 161 CHECK(inner_map_map, op, &iv->lock, &v->head, &f->node2); 162 163CHECK_OP(push_front); 164CHECK_OP(push_back); 165 166#undef CHECK 167#undef CHECK_OP 168#undef INIT 169 170SEC("?kprobe/xyz") 171int map_compat_kprobe(void *ctx) 172{ 173 bpf_list_push_front(&ghead, NULL); 174 return 0; 175} 176 177SEC("?kretprobe/xyz") 178int map_compat_kretprobe(void *ctx) 179{ 180 bpf_list_push_front(&ghead, NULL); 181 return 0; 182} 183 184SEC("?tracepoint/xyz") 185int map_compat_tp(void *ctx) 186{ 187 bpf_list_push_front(&ghead, NULL); 188 return 0; 189} 190 191SEC("?perf_event") 192int map_compat_perf(void *ctx) 193{ 194 bpf_list_push_front(&ghead, NULL); 195 return 0; 196} 197 198SEC("?raw_tp/xyz") 199int map_compat_raw_tp(void *ctx) 200{ 201 bpf_list_push_front(&ghead, NULL); 202 return 0; 203} 204 205SEC("?raw_tp.w/xyz") 206int map_compat_raw_tp_w(void *ctx) 207{ 208 bpf_list_push_front(&ghead, NULL); 209 return 0; 210} 211 212SEC("?tc") 213int obj_type_id_oor(void *ctx) 214{ 215 bpf_obj_new_impl(~0UL, NULL); 216 return 0; 217} 218 219SEC("?tc") 220int obj_new_no_composite(void *ctx) 221{ 222 bpf_obj_new_impl(bpf_core_type_id_local(int), (void *)42); 223 return 0; 224} 225 226SEC("?tc") 227int obj_new_no_struct(void *ctx) 228{ 229 (void)bpf_obj_new(union { int data; unsigned udata; }); 230 return 0; 231} 232 233SEC("?tc") 234int obj_drop_non_zero_off(void *ctx) 235{ 236 void *f; 237 238 f = bpf_obj_new(struct foo); 239 if (!f) 240 return 0; 241 bpf_obj_drop(f+1); 242 return 0; 243} 244 245SEC("?tc") 246int new_null_ret(void *ctx) 247{ 248 return bpf_obj_new(struct foo)->data; 249} 250 251SEC("?tc") 252int obj_new_acq(void *ctx) 253{ 254 (void)bpf_obj_new(struct foo); 255 return 0; 256} 257 258SEC("?tc") 259int use_after_drop(void *ctx) 260{ 261 struct foo *f; 262 263 f = bpf_obj_new(typeof(*f)); 264 if (!f) 265 return 0; 266 bpf_obj_drop(f); 267 return f->data; 268} 269 270SEC("?tc") 271int ptr_walk_scalar(void *ctx) 272{ 273 struct test1 { 274 struct test2 { 275 struct test2 *next; 276 } *ptr; 277 } *p; 278 279 p = bpf_obj_new(typeof(*p)); 280 if (!p) 281 return 0; 282 bpf_this_cpu_ptr(p->ptr); 283 return 0; 284} 285 286SEC("?tc") 287int direct_read_lock(void *ctx) 288{ 289 struct foo *f; 290 291 f = bpf_obj_new(typeof(*f)); 292 if (!f) 293 return 0; 294 return *(int *)&f->lock; 295} 296 297SEC("?tc") 298int direct_write_lock(void *ctx) 299{ 300 struct foo *f; 301 302 f = bpf_obj_new(typeof(*f)); 303 if (!f) 304 return 0; 305 *(int *)&f->lock = 0; 306 return 0; 307} 308 309SEC("?tc") 310int direct_read_head(void *ctx) 311{ 312 struct foo *f; 313 314 f = bpf_obj_new(typeof(*f)); 315 if (!f) 316 return 0; 317 return *(int *)&f->head; 318} 319 320SEC("?tc") 321int direct_write_head(void *ctx) 322{ 323 struct foo *f; 324 325 f = bpf_obj_new(typeof(*f)); 326 if (!f) 327 return 0; 328 *(int *)&f->head = 0; 329 return 0; 330} 331 332SEC("?tc") 333int direct_read_node(void *ctx) 334{ 335 struct foo *f; 336 337 f = bpf_obj_new(typeof(*f)); 338 if (!f) 339 return 0; 340 return *(int *)&f->node2; 341} 342 343SEC("?tc") 344int direct_write_node(void *ctx) 345{ 346 struct foo *f; 347 348 f = bpf_obj_new(typeof(*f)); 349 if (!f) 350 return 0; 351 *(int *)&f->node2 = 0; 352 return 0; 353} 354 355static __always_inline 356int use_after_unlock(bool push_front) 357{ 358 struct foo *f; 359 360 f = bpf_obj_new(typeof(*f)); 361 if (!f) 362 return 0; 363 bpf_spin_lock(&glock); 364 f->data = 42; 365 if (push_front) 366 bpf_list_push_front(&ghead, &f->node2); 367 else 368 bpf_list_push_back(&ghead, &f->node2); 369 bpf_spin_unlock(&glock); 370 371 return f->data; 372} 373 374SEC("?tc") 375int use_after_unlock_push_front(void *ctx) 376{ 377 return use_after_unlock(true); 378} 379 380SEC("?tc") 381int use_after_unlock_push_back(void *ctx) 382{ 383 return use_after_unlock(false); 384} 385 386static __always_inline 387int list_double_add(bool push_front) 388{ 389 struct foo *f; 390 391 f = bpf_obj_new(typeof(*f)); 392 if (!f) 393 return 0; 394 bpf_spin_lock(&glock); 395 if (push_front) { 396 bpf_list_push_front(&ghead, &f->node2); 397 bpf_list_push_front(&ghead, &f->node2); 398 } else { 399 bpf_list_push_back(&ghead, &f->node2); 400 bpf_list_push_back(&ghead, &f->node2); 401 } 402 bpf_spin_unlock(&glock); 403 404 return 0; 405} 406 407SEC("?tc") 408int double_push_front(void *ctx) 409{ 410 return list_double_add(true); 411} 412 413SEC("?tc") 414int double_push_back(void *ctx) 415{ 416 return list_double_add(false); 417} 418 419SEC("?tc") 420int no_node_value_type(void *ctx) 421{ 422 void *p; 423 424 p = bpf_obj_new(struct { int data; }); 425 if (!p) 426 return 0; 427 bpf_spin_lock(&glock); 428 bpf_list_push_front(&ghead, p); 429 bpf_spin_unlock(&glock); 430 431 return 0; 432} 433 434SEC("?tc") 435int incorrect_value_type(void *ctx) 436{ 437 struct bar *b; 438 439 b = bpf_obj_new(typeof(*b)); 440 if (!b) 441 return 0; 442 bpf_spin_lock(&glock); 443 bpf_list_push_front(&ghead, &b->node); 444 bpf_spin_unlock(&glock); 445 446 return 0; 447} 448 449SEC("?tc") 450int incorrect_node_var_off(struct __sk_buff *ctx) 451{ 452 struct foo *f; 453 454 f = bpf_obj_new(typeof(*f)); 455 if (!f) 456 return 0; 457 bpf_spin_lock(&glock); 458 bpf_list_push_front(&ghead, (void *)&f->node2 + ctx->protocol); 459 bpf_spin_unlock(&glock); 460 461 return 0; 462} 463 464SEC("?tc") 465int incorrect_node_off1(void *ctx) 466{ 467 struct foo *f; 468 469 f = bpf_obj_new(typeof(*f)); 470 if (!f) 471 return 0; 472 bpf_spin_lock(&glock); 473 bpf_list_push_front(&ghead, (void *)&f->node2 + 1); 474 bpf_spin_unlock(&glock); 475 476 return 0; 477} 478 479SEC("?tc") 480int incorrect_node_off2(void *ctx) 481{ 482 struct foo *f; 483 484 f = bpf_obj_new(typeof(*f)); 485 if (!f) 486 return 0; 487 bpf_spin_lock(&glock); 488 bpf_list_push_front(&ghead, &f->node); 489 bpf_spin_unlock(&glock); 490 491 return 0; 492} 493 494SEC("?tc") 495int no_head_type(void *ctx) 496{ 497 void *p; 498 499 p = bpf_obj_new(typeof(struct { int data; })); 500 if (!p) 501 return 0; 502 bpf_spin_lock(&glock); 503 bpf_list_push_front(p, NULL); 504 bpf_spin_lock(&glock); 505 506 return 0; 507} 508 509SEC("?tc") 510int incorrect_head_var_off1(struct __sk_buff *ctx) 511{ 512 struct foo *f; 513 514 f = bpf_obj_new(typeof(*f)); 515 if (!f) 516 return 0; 517 bpf_spin_lock(&glock); 518 bpf_list_push_front((void *)&ghead + ctx->protocol, &f->node2); 519 bpf_spin_unlock(&glock); 520 521 return 0; 522} 523 524SEC("?tc") 525int incorrect_head_var_off2(struct __sk_buff *ctx) 526{ 527 struct foo *f; 528 529 f = bpf_obj_new(typeof(*f)); 530 if (!f) 531 return 0; 532 bpf_spin_lock(&glock); 533 bpf_list_push_front((void *)&f->head + ctx->protocol, &f->node2); 534 bpf_spin_unlock(&glock); 535 536 return 0; 537} 538 539SEC("?tc") 540int incorrect_head_off1(void *ctx) 541{ 542 struct foo *f; 543 struct bar *b; 544 545 f = bpf_obj_new(typeof(*f)); 546 if (!f) 547 return 0; 548 b = bpf_obj_new(typeof(*b)); 549 if (!b) { 550 bpf_obj_drop(f); 551 return 0; 552 } 553 554 bpf_spin_lock(&f->lock); 555 bpf_list_push_front((void *)&f->head + 1, &b->node); 556 bpf_spin_unlock(&f->lock); 557 558 return 0; 559} 560 561SEC("?tc") 562int incorrect_head_off2(void *ctx) 563{ 564 struct foo *f; 565 566 f = bpf_obj_new(typeof(*f)); 567 if (!f) 568 return 0; 569 570 bpf_spin_lock(&glock); 571 bpf_list_push_front((void *)&ghead + 1, &f->node2); 572 bpf_spin_unlock(&glock); 573 574 return 0; 575} 576 577static __always_inline 578int pop_ptr_off(void *(*op)(void *head)) 579{ 580 struct { 581 struct bpf_list_head head __contains(foo, node2); 582 struct bpf_spin_lock lock; 583 } *p; 584 struct bpf_list_node *n; 585 586 p = bpf_obj_new(typeof(*p)); 587 if (!p) 588 return 0; 589 bpf_spin_lock(&p->lock); 590 n = op(&p->head); 591 bpf_spin_unlock(&p->lock); 592 593 if (!n) 594 return 0; 595 bpf_spin_lock((void *)n); 596 return 0; 597} 598 599SEC("?tc") 600int pop_front_off(void *ctx) 601{ 602 return pop_ptr_off((void *)bpf_list_pop_front); 603} 604 605SEC("?tc") 606int pop_back_off(void *ctx) 607{ 608 return pop_ptr_off((void *)bpf_list_pop_back); 609} 610 611char _license[] SEC("license") = "GPL";