Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Kumar Kartikeya Dwivedi | 1720 | 78.22% | 3 | 50.00% |
Alexei Starovoitov | 324 | 14.73% | 1 | 16.67% |
Dave Marchevsky | 155 | 7.05% | 2 | 33.33% |
Total | 2199 | 6 |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
// SPDX-License-Identifier: GPL-2.0 #include <vmlinux.h> #include <bpf/bpf_tracing.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_core_read.h> #include "bpf_experimental.h" #include "linked_list.h" #define INIT \ struct map_value *v, *v2, *iv, *iv2; \ struct foo *f, *f1, *f2; \ struct bar *b; \ void *map; \ \ map = bpf_map_lookup_elem(&map_of_maps, &(int){ 0 }); \ if (!map) \ return 0; \ v = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \ if (!v) \ return 0; \ v2 = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \ if (!v2) \ return 0; \ iv = bpf_map_lookup_elem(map, &(int){ 0 }); \ if (!iv) \ return 0; \ iv2 = bpf_map_lookup_elem(map, &(int){ 0 }); \ if (!iv2) \ return 0; \ f = bpf_obj_new(typeof(*f)); \ if (!f) \ return 0; \ f1 = f; \ f2 = bpf_obj_new(typeof(*f2)); \ if (!f2) { \ bpf_obj_drop(f1); \ return 0; \ } \ b = bpf_obj_new(typeof(*b)); \ if (!b) { \ bpf_obj_drop(f2); \ bpf_obj_drop(f1); \ return 0; \ } #define CHECK(test, op, hexpr) \ SEC("?tc") \ int test##_missing_lock_##op(void *ctx) \ { \ INIT; \ void (*p)(void *) = (void *)&bpf_list_##op; \ p(hexpr); \ return 0; \ } CHECK(kptr, pop_front, &f->head); CHECK(kptr, pop_back, &f->head); CHECK(global, pop_front, &ghead); CHECK(global, pop_back, &ghead); CHECK(map, pop_front, &v->head); CHECK(map, pop_back, &v->head); CHECK(inner_map, pop_front, &iv->head); CHECK(inner_map, pop_back, &iv->head); #undef CHECK #define CHECK(test, op, hexpr, nexpr) \ SEC("?tc") \ int test##_missing_lock_##op(void *ctx) \ { \ INIT; \ bpf_list_##op(hexpr, nexpr); \ return 0; \ } CHECK(kptr, push_front, &f->head, &b->node); CHECK(kptr, push_back, &f->head, &b->node); CHECK(global, push_front, &ghead, &f->node2); CHECK(global, push_back, &ghead, &f->node2); CHECK(map, push_front, &v->head, &f->node2); CHECK(map, push_back, &v->head, &f->node2); CHECK(inner_map, push_front, &iv->head, &f->node2); CHECK(inner_map, push_back, &iv->head, &f->node2); #undef CHECK #define CHECK(test, op, lexpr, hexpr) \ SEC("?tc") \ int test##_incorrect_lock_##op(void *ctx) \ { \ INIT; \ void (*p)(void *) = (void *)&bpf_list_##op; \ bpf_spin_lock(lexpr); \ p(hexpr); \ return 0; \ } #define CHECK_OP(op) \ CHECK(kptr_kptr, op, &f1->lock, &f2->head); \ CHECK(kptr_global, op, &f1->lock, &ghead); \ CHECK(kptr_map, op, &f1->lock, &v->head); \ CHECK(kptr_inner_map, op, &f1->lock, &iv->head); \ \ CHECK(global_global, op, &glock2, &ghead); \ CHECK(global_kptr, op, &glock, &f1->head); \ CHECK(global_map, op, &glock, &v->head); \ CHECK(global_inner_map, op, &glock, &iv->head); \ \ CHECK(map_map, op, &v->lock, &v2->head); \ CHECK(map_kptr, op, &v->lock, &f2->head); \ CHECK(map_global, op, &v->lock, &ghead); \ CHECK(map_inner_map, op, &v->lock, &iv->head); \ \ CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head); \ CHECK(inner_map_kptr, op, &iv->lock, &f2->head); \ CHECK(inner_map_global, op, &iv->lock, &ghead); \ CHECK(inner_map_map, op, &iv->lock, &v->head); CHECK_OP(pop_front); CHECK_OP(pop_back); #undef CHECK #undef CHECK_OP #define CHECK(test, op, lexpr, hexpr, nexpr) \ SEC("?tc") \ int test##_incorrect_lock_##op(void *ctx) \ { \ INIT; \ bpf_spin_lock(lexpr); \ bpf_list_##op(hexpr, nexpr); \ return 0; \ } #define CHECK_OP(op) \ CHECK(kptr_kptr, op, &f1->lock, &f2->head, &b->node); \ CHECK(kptr_global, op, &f1->lock, &ghead, &f->node2); \ CHECK(kptr_map, op, &f1->lock, &v->head, &f->node2); \ CHECK(kptr_inner_map, op, &f1->lock, &iv->head, &f->node2); \ \ CHECK(global_global, op, &glock2, &ghead, &f->node2); \ CHECK(global_kptr, op, &glock, &f1->head, &b->node); \ CHECK(global_map, op, &glock, &v->head, &f->node2); \ CHECK(global_inner_map, op, &glock, &iv->head, &f->node2); \ \ CHECK(map_map, op, &v->lock, &v2->head, &f->node2); \ CHECK(map_kptr, op, &v->lock, &f2->head, &b->node); \ CHECK(map_global, op, &v->lock, &ghead, &f->node2); \ CHECK(map_inner_map, op, &v->lock, &iv->head, &f->node2); \ \ CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head, &f->node2);\ CHECK(inner_map_kptr, op, &iv->lock, &f2->head, &b->node); \ CHECK(inner_map_global, op, &iv->lock, &ghead, &f->node2); \ CHECK(inner_map_map, op, &iv->lock, &v->head, &f->node2); CHECK_OP(push_front); CHECK_OP(push_back); #undef CHECK #undef CHECK_OP #undef INIT SEC("?kprobe/xyz") int map_compat_kprobe(void *ctx) { bpf_list_push_front(&ghead, NULL); return 0; } SEC("?kretprobe/xyz") int map_compat_kretprobe(void *ctx) { bpf_list_push_front(&ghead, NULL); return 0; } SEC("?tracepoint/xyz") int map_compat_tp(void *ctx) { bpf_list_push_front(&ghead, NULL); return 0; } SEC("?perf_event") int map_compat_perf(void *ctx) { bpf_list_push_front(&ghead, NULL); return 0; } SEC("?raw_tp/xyz") int map_compat_raw_tp(void *ctx) { bpf_list_push_front(&ghead, NULL); return 0; } SEC("?raw_tp.w/xyz") int map_compat_raw_tp_w(void *ctx) { bpf_list_push_front(&ghead, NULL); return 0; } SEC("?tc") int obj_type_id_oor(void *ctx) { bpf_obj_new_impl(~0UL, NULL); return 0; } SEC("?tc") int obj_new_no_composite(void *ctx) { bpf_obj_new_impl(bpf_core_type_id_local(int), (void *)42); return 0; } SEC("?tc") int obj_new_no_struct(void *ctx) { bpf_obj_new(union { int data; unsigned udata; }); return 0; } SEC("?tc") int obj_drop_non_zero_off(void *ctx) { void *f; f = bpf_obj_new(struct foo); if (!f) return 0; bpf_obj_drop(f+1); return 0; } SEC("?tc") int new_null_ret(void *ctx) { return bpf_obj_new(struct foo)->data; } SEC("?tc") int obj_new_acq(void *ctx) { bpf_obj_new(struct foo); return 0; } SEC("?tc") int use_after_drop(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_obj_drop(f); return f->data; } SEC("?tc") int ptr_walk_scalar(void *ctx) { struct test1 { struct test2 { struct test2 *next; } *ptr; } *p; p = bpf_obj_new(typeof(*p)); if (!p) return 0; bpf_this_cpu_ptr(p->ptr); return 0; } SEC("?tc") int direct_read_lock(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; return *(int *)&f->lock; } SEC("?tc") int direct_write_lock(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; *(int *)&f->lock = 0; return 0; } SEC("?tc") int direct_read_head(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; return *(int *)&f->head; } SEC("?tc") int direct_write_head(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; *(int *)&f->head = 0; return 0; } SEC("?tc") int direct_read_node(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; return *(int *)&f->node2; } SEC("?tc") int direct_write_node(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; *(int *)&f->node2 = 0; return 0; } static __always_inline int use_after_unlock(bool push_front) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); f->data = 42; if (push_front) bpf_list_push_front(&ghead, &f->node2); else bpf_list_push_back(&ghead, &f->node2); bpf_spin_unlock(&glock); return f->data; } SEC("?tc") int use_after_unlock_push_front(void *ctx) { return use_after_unlock(true); } SEC("?tc") int use_after_unlock_push_back(void *ctx) { return use_after_unlock(false); } static __always_inline int list_double_add(bool push_front) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); if (push_front) { bpf_list_push_front(&ghead, &f->node2); bpf_list_push_front(&ghead, &f->node2); } else { bpf_list_push_back(&ghead, &f->node2); bpf_list_push_back(&ghead, &f->node2); } bpf_spin_unlock(&glock); return 0; } SEC("?tc") int double_push_front(void *ctx) { return list_double_add(true); } SEC("?tc") int double_push_back(void *ctx) { return list_double_add(false); } SEC("?tc") int no_node_value_type(void *ctx) { void *p; p = bpf_obj_new(struct { int data; }); if (!p) return 0; bpf_spin_lock(&glock); bpf_list_push_front(&ghead, p); bpf_spin_unlock(&glock); return 0; } SEC("?tc") int incorrect_value_type(void *ctx) { struct bar *b; b = bpf_obj_new(typeof(*b)); if (!b) return 0; bpf_spin_lock(&glock); bpf_list_push_front(&ghead, &b->node); bpf_spin_unlock(&glock); return 0; } SEC("?tc") int incorrect_node_var_off(struct __sk_buff *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); bpf_list_push_front(&ghead, (void *)&f->node2 + ctx->protocol); bpf_spin_unlock(&glock); return 0; } SEC("?tc") int incorrect_node_off1(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); bpf_list_push_front(&ghead, (void *)&f->node2 + 1); bpf_spin_unlock(&glock); return 0; } SEC("?tc") int incorrect_node_off2(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); bpf_list_push_front(&ghead, &f->node); bpf_spin_unlock(&glock); return 0; } SEC("?tc") int no_head_type(void *ctx) { void *p; p = bpf_obj_new(typeof(struct { int data; })); if (!p) return 0; bpf_spin_lock(&glock); bpf_list_push_front(p, NULL); bpf_spin_lock(&glock); return 0; } SEC("?tc") int incorrect_head_var_off1(struct __sk_buff *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); bpf_list_push_front((void *)&ghead + ctx->protocol, &f->node2); bpf_spin_unlock(&glock); return 0; } SEC("?tc") int incorrect_head_var_off2(struct __sk_buff *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); bpf_list_push_front((void *)&f->head + ctx->protocol, &f->node2); bpf_spin_unlock(&glock); return 0; } SEC("?tc") int incorrect_head_off1(void *ctx) { struct foo *f; struct bar *b; f = bpf_obj_new(typeof(*f)); if (!f) return 0; b = bpf_obj_new(typeof(*b)); if (!b) { bpf_obj_drop(f); return 0; } bpf_spin_lock(&f->lock); bpf_list_push_front((void *)&f->head + 1, &b->node); bpf_spin_unlock(&f->lock); return 0; } SEC("?tc") int incorrect_head_off2(void *ctx) { struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 0; bpf_spin_lock(&glock); bpf_list_push_front((void *)&ghead + 1, &f->node2); bpf_spin_unlock(&glock); return 0; } static __always_inline int pop_ptr_off(void *(*op)(void *head)) { struct { struct bpf_list_head head __contains(foo, node2); struct bpf_spin_lock lock; } *p; struct bpf_list_node *n; p = bpf_obj_new(typeof(*p)); if (!p) return 0; bpf_spin_lock(&p->lock); n = op(&p->head); bpf_spin_unlock(&p->lock); if (!n) return 0; bpf_spin_lock((void *)n); return 0; } SEC("?tc") int pop_front_off(void *ctx) { return pop_ptr_off((void *)bpf_list_pop_front); } SEC("?tc") int pop_back_off(void *ctx) { return pop_ptr_off((void *)bpf_list_pop_back); } char _license[] SEC("license") = "GPL";
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1