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