162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <vmlinux.h> 362306a36Sopenharmony_ci#include <bpf/bpf_tracing.h> 462306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 562306a36Sopenharmony_ci#include "../bpf_testmod/bpf_testmod_kfunc.h" 662306a36Sopenharmony_ci 762306a36Sopenharmony_cistruct map_value { 862306a36Sopenharmony_ci struct prog_test_ref_kfunc __kptr_untrusted *unref_ptr; 962306a36Sopenharmony_ci struct prog_test_ref_kfunc __kptr *ref_ptr; 1062306a36Sopenharmony_ci}; 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistruct array_map { 1362306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_ARRAY); 1462306a36Sopenharmony_ci __type(key, int); 1562306a36Sopenharmony_ci __type(value, struct map_value); 1662306a36Sopenharmony_ci __uint(max_entries, 1); 1762306a36Sopenharmony_ci} array_map SEC(".maps"); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistruct pcpu_array_map { 2062306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 2162306a36Sopenharmony_ci __type(key, int); 2262306a36Sopenharmony_ci __type(value, struct map_value); 2362306a36Sopenharmony_ci __uint(max_entries, 1); 2462306a36Sopenharmony_ci} pcpu_array_map SEC(".maps"); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct hash_map { 2762306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 2862306a36Sopenharmony_ci __type(key, int); 2962306a36Sopenharmony_ci __type(value, struct map_value); 3062306a36Sopenharmony_ci __uint(max_entries, 1); 3162306a36Sopenharmony_ci} hash_map SEC(".maps"); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistruct pcpu_hash_map { 3462306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 3562306a36Sopenharmony_ci __type(key, int); 3662306a36Sopenharmony_ci __type(value, struct map_value); 3762306a36Sopenharmony_ci __uint(max_entries, 1); 3862306a36Sopenharmony_ci} pcpu_hash_map SEC(".maps"); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct hash_malloc_map { 4162306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 4262306a36Sopenharmony_ci __type(key, int); 4362306a36Sopenharmony_ci __type(value, struct map_value); 4462306a36Sopenharmony_ci __uint(max_entries, 1); 4562306a36Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC); 4662306a36Sopenharmony_ci} hash_malloc_map SEC(".maps"); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistruct pcpu_hash_malloc_map { 4962306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 5062306a36Sopenharmony_ci __type(key, int); 5162306a36Sopenharmony_ci __type(value, struct map_value); 5262306a36Sopenharmony_ci __uint(max_entries, 1); 5362306a36Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC); 5462306a36Sopenharmony_ci} pcpu_hash_malloc_map SEC(".maps"); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistruct lru_hash_map { 5762306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_LRU_HASH); 5862306a36Sopenharmony_ci __type(key, int); 5962306a36Sopenharmony_ci __type(value, struct map_value); 6062306a36Sopenharmony_ci __uint(max_entries, 1); 6162306a36Sopenharmony_ci} lru_hash_map SEC(".maps"); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistruct lru_pcpu_hash_map { 6462306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_LRU_PERCPU_HASH); 6562306a36Sopenharmony_ci __type(key, int); 6662306a36Sopenharmony_ci __type(value, struct map_value); 6762306a36Sopenharmony_ci __uint(max_entries, 1); 6862306a36Sopenharmony_ci} lru_pcpu_hash_map SEC(".maps"); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistruct cgrp_ls_map { 7162306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_CGRP_STORAGE); 7262306a36Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC); 7362306a36Sopenharmony_ci __type(key, int); 7462306a36Sopenharmony_ci __type(value, struct map_value); 7562306a36Sopenharmony_ci} cgrp_ls_map SEC(".maps"); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistruct task_ls_map { 7862306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_TASK_STORAGE); 7962306a36Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC); 8062306a36Sopenharmony_ci __type(key, int); 8162306a36Sopenharmony_ci __type(value, struct map_value); 8262306a36Sopenharmony_ci} task_ls_map SEC(".maps"); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistruct inode_ls_map { 8562306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_INODE_STORAGE); 8662306a36Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC); 8762306a36Sopenharmony_ci __type(key, int); 8862306a36Sopenharmony_ci __type(value, struct map_value); 8962306a36Sopenharmony_ci} inode_ls_map SEC(".maps"); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistruct sk_ls_map { 9262306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_SK_STORAGE); 9362306a36Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC); 9462306a36Sopenharmony_ci __type(key, int); 9562306a36Sopenharmony_ci __type(value, struct map_value); 9662306a36Sopenharmony_ci} sk_ls_map SEC(".maps"); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#define DEFINE_MAP_OF_MAP(map_type, inner_map_type, name) \ 9962306a36Sopenharmony_ci struct { \ 10062306a36Sopenharmony_ci __uint(type, map_type); \ 10162306a36Sopenharmony_ci __uint(max_entries, 1); \ 10262306a36Sopenharmony_ci __uint(key_size, sizeof(int)); \ 10362306a36Sopenharmony_ci __uint(value_size, sizeof(int)); \ 10462306a36Sopenharmony_ci __array(values, struct inner_map_type); \ 10562306a36Sopenharmony_ci } name SEC(".maps") = { \ 10662306a36Sopenharmony_ci .values = { [0] = &inner_map_type }, \ 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_map, array_of_array_maps); 11062306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_map, array_of_hash_maps); 11162306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_malloc_map, array_of_hash_malloc_maps); 11262306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, lru_hash_map, array_of_lru_hash_maps); 11362306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, array_map, hash_of_array_maps); 11462306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_map, hash_of_hash_maps); 11562306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_malloc_map, hash_of_hash_malloc_maps); 11662306a36Sopenharmony_ciDEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, lru_hash_map, hash_of_lru_hash_maps); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val)) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic void test_kptr_unref(struct map_value *v) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct prog_test_ref_kfunc *p; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci p = v->unref_ptr; 12562306a36Sopenharmony_ci /* store untrusted_ptr_or_null_ */ 12662306a36Sopenharmony_ci WRITE_ONCE(v->unref_ptr, p); 12762306a36Sopenharmony_ci if (!p) 12862306a36Sopenharmony_ci return; 12962306a36Sopenharmony_ci if (p->a + p->b > 100) 13062306a36Sopenharmony_ci return; 13162306a36Sopenharmony_ci /* store untrusted_ptr_ */ 13262306a36Sopenharmony_ci WRITE_ONCE(v->unref_ptr, p); 13362306a36Sopenharmony_ci /* store NULL */ 13462306a36Sopenharmony_ci WRITE_ONCE(v->unref_ptr, NULL); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic void test_kptr_ref(struct map_value *v) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci struct prog_test_ref_kfunc *p; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci p = v->ref_ptr; 14262306a36Sopenharmony_ci /* store ptr_or_null_ */ 14362306a36Sopenharmony_ci WRITE_ONCE(v->unref_ptr, p); 14462306a36Sopenharmony_ci if (!p) 14562306a36Sopenharmony_ci return; 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * p is rcu_ptr_prog_test_ref_kfunc, 14862306a36Sopenharmony_ci * because bpf prog is non-sleepable and runs in RCU CS. 14962306a36Sopenharmony_ci * p can be passed to kfunc that requires KF_RCU. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci bpf_kfunc_call_test_ref(p); 15262306a36Sopenharmony_ci if (p->a + p->b > 100) 15362306a36Sopenharmony_ci return; 15462306a36Sopenharmony_ci /* store NULL */ 15562306a36Sopenharmony_ci p = bpf_kptr_xchg(&v->ref_ptr, NULL); 15662306a36Sopenharmony_ci if (!p) 15762306a36Sopenharmony_ci return; 15862306a36Sopenharmony_ci /* 15962306a36Sopenharmony_ci * p is trusted_ptr_prog_test_ref_kfunc. 16062306a36Sopenharmony_ci * p can be passed to kfunc that requires KF_RCU. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_ci bpf_kfunc_call_test_ref(p); 16362306a36Sopenharmony_ci if (p->a + p->b > 100) { 16462306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 16562306a36Sopenharmony_ci return; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci /* store ptr_ */ 16862306a36Sopenharmony_ci WRITE_ONCE(v->unref_ptr, p); 16962306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci p = bpf_kfunc_call_test_acquire(&(unsigned long){0}); 17262306a36Sopenharmony_ci if (!p) 17362306a36Sopenharmony_ci return; 17462306a36Sopenharmony_ci /* store ptr_ */ 17562306a36Sopenharmony_ci p = bpf_kptr_xchg(&v->ref_ptr, p); 17662306a36Sopenharmony_ci if (!p) 17762306a36Sopenharmony_ci return; 17862306a36Sopenharmony_ci if (p->a + p->b > 100) { 17962306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 18062306a36Sopenharmony_ci return; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic void test_kptr(struct map_value *v) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci test_kptr_unref(v); 18862306a36Sopenharmony_ci test_kptr_ref(v); 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciSEC("tc") 19262306a36Sopenharmony_ciint test_map_kptr(struct __sk_buff *ctx) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct map_value *v; 19562306a36Sopenharmony_ci int key = 0; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#define TEST(map) \ 19862306a36Sopenharmony_ci v = bpf_map_lookup_elem(&map, &key); \ 19962306a36Sopenharmony_ci if (!v) \ 20062306a36Sopenharmony_ci return 0; \ 20162306a36Sopenharmony_ci test_kptr(v) 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci TEST(array_map); 20462306a36Sopenharmony_ci TEST(hash_map); 20562306a36Sopenharmony_ci TEST(hash_malloc_map); 20662306a36Sopenharmony_ci TEST(lru_hash_map); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#undef TEST 20962306a36Sopenharmony_ci return 0; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ciSEC("tp_btf/cgroup_mkdir") 21362306a36Sopenharmony_ciint BPF_PROG(test_cgrp_map_kptr, struct cgroup *cgrp, const char *path) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct map_value *v; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci v = bpf_cgrp_storage_get(&cgrp_ls_map, cgrp, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE); 21862306a36Sopenharmony_ci if (v) 21962306a36Sopenharmony_ci test_kptr(v); 22062306a36Sopenharmony_ci return 0; 22162306a36Sopenharmony_ci} 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciSEC("lsm/inode_unlink") 22462306a36Sopenharmony_ciint BPF_PROG(test_task_map_kptr, struct inode *inode, struct dentry *victim) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci struct task_struct *task; 22762306a36Sopenharmony_ci struct map_value *v; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci task = bpf_get_current_task_btf(); 23062306a36Sopenharmony_ci if (!task) 23162306a36Sopenharmony_ci return 0; 23262306a36Sopenharmony_ci v = bpf_task_storage_get(&task_ls_map, task, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE); 23362306a36Sopenharmony_ci if (v) 23462306a36Sopenharmony_ci test_kptr(v); 23562306a36Sopenharmony_ci return 0; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ciSEC("lsm/inode_unlink") 23962306a36Sopenharmony_ciint BPF_PROG(test_inode_map_kptr, struct inode *inode, struct dentry *victim) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct map_value *v; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci v = bpf_inode_storage_get(&inode_ls_map, inode, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE); 24462306a36Sopenharmony_ci if (v) 24562306a36Sopenharmony_ci test_kptr(v); 24662306a36Sopenharmony_ci return 0; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ciSEC("tc") 25062306a36Sopenharmony_ciint test_sk_map_kptr(struct __sk_buff *ctx) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct map_value *v; 25362306a36Sopenharmony_ci struct bpf_sock *sk; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci sk = ctx->sk; 25662306a36Sopenharmony_ci if (!sk) 25762306a36Sopenharmony_ci return 0; 25862306a36Sopenharmony_ci v = bpf_sk_storage_get(&sk_ls_map, sk, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE); 25962306a36Sopenharmony_ci if (v) 26062306a36Sopenharmony_ci test_kptr(v); 26162306a36Sopenharmony_ci return 0; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ciSEC("tc") 26562306a36Sopenharmony_ciint test_map_in_map_kptr(struct __sk_buff *ctx) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct map_value *v; 26862306a36Sopenharmony_ci int key = 0; 26962306a36Sopenharmony_ci void *map; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci#define TEST(map_in_map) \ 27262306a36Sopenharmony_ci map = bpf_map_lookup_elem(&map_in_map, &key); \ 27362306a36Sopenharmony_ci if (!map) \ 27462306a36Sopenharmony_ci return 0; \ 27562306a36Sopenharmony_ci v = bpf_map_lookup_elem(map, &key); \ 27662306a36Sopenharmony_ci if (!v) \ 27762306a36Sopenharmony_ci return 0; \ 27862306a36Sopenharmony_ci test_kptr(v) 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci TEST(array_of_array_maps); 28162306a36Sopenharmony_ci TEST(array_of_hash_maps); 28262306a36Sopenharmony_ci TEST(array_of_hash_malloc_maps); 28362306a36Sopenharmony_ci TEST(array_of_lru_hash_maps); 28462306a36Sopenharmony_ci TEST(hash_of_array_maps); 28562306a36Sopenharmony_ci TEST(hash_of_hash_maps); 28662306a36Sopenharmony_ci TEST(hash_of_hash_malloc_maps); 28762306a36Sopenharmony_ci TEST(hash_of_lru_hash_maps); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci#undef TEST 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ciint ref = 1; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic __always_inline 29662306a36Sopenharmony_ciint test_map_kptr_ref_pre(struct map_value *v) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct prog_test_ref_kfunc *p, *p_st; 29962306a36Sopenharmony_ci unsigned long arg = 0; 30062306a36Sopenharmony_ci int ret; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci p = bpf_kfunc_call_test_acquire(&arg); 30362306a36Sopenharmony_ci if (!p) 30462306a36Sopenharmony_ci return 1; 30562306a36Sopenharmony_ci ref++; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci p_st = p->next; 30862306a36Sopenharmony_ci if (p_st->cnt.refs.counter != ref) { 30962306a36Sopenharmony_ci ret = 2; 31062306a36Sopenharmony_ci goto end; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci p = bpf_kptr_xchg(&v->ref_ptr, p); 31462306a36Sopenharmony_ci if (p) { 31562306a36Sopenharmony_ci ret = 3; 31662306a36Sopenharmony_ci goto end; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci if (p_st->cnt.refs.counter != ref) 31962306a36Sopenharmony_ci return 4; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci p = bpf_kptr_xchg(&v->ref_ptr, NULL); 32262306a36Sopenharmony_ci if (!p) 32362306a36Sopenharmony_ci return 5; 32462306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 32562306a36Sopenharmony_ci ref--; 32662306a36Sopenharmony_ci if (p_st->cnt.refs.counter != ref) 32762306a36Sopenharmony_ci return 6; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci p = bpf_kfunc_call_test_acquire(&arg); 33062306a36Sopenharmony_ci if (!p) 33162306a36Sopenharmony_ci return 7; 33262306a36Sopenharmony_ci ref++; 33362306a36Sopenharmony_ci p = bpf_kptr_xchg(&v->ref_ptr, p); 33462306a36Sopenharmony_ci if (p) { 33562306a36Sopenharmony_ci ret = 8; 33662306a36Sopenharmony_ci goto end; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci if (p_st->cnt.refs.counter != ref) 33962306a36Sopenharmony_ci return 9; 34062306a36Sopenharmony_ci /* Leave in map */ 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci return 0; 34362306a36Sopenharmony_ciend: 34462306a36Sopenharmony_ci ref--; 34562306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 34662306a36Sopenharmony_ci return ret; 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic __always_inline 35062306a36Sopenharmony_ciint test_map_kptr_ref_post(struct map_value *v) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci struct prog_test_ref_kfunc *p, *p_st; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci p_st = v->ref_ptr; 35562306a36Sopenharmony_ci if (!p_st || p_st->cnt.refs.counter != ref) 35662306a36Sopenharmony_ci return 1; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci p = bpf_kptr_xchg(&v->ref_ptr, NULL); 35962306a36Sopenharmony_ci if (!p) 36062306a36Sopenharmony_ci return 2; 36162306a36Sopenharmony_ci if (p_st->cnt.refs.counter != ref) { 36262306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 36362306a36Sopenharmony_ci return 3; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci p = bpf_kptr_xchg(&v->ref_ptr, p); 36762306a36Sopenharmony_ci if (p) { 36862306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 36962306a36Sopenharmony_ci return 4; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci if (p_st->cnt.refs.counter != ref) 37262306a36Sopenharmony_ci return 5; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci return 0; 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci#define TEST(map) \ 37862306a36Sopenharmony_ci v = bpf_map_lookup_elem(&map, &key); \ 37962306a36Sopenharmony_ci if (!v) \ 38062306a36Sopenharmony_ci return -1; \ 38162306a36Sopenharmony_ci ret = test_map_kptr_ref_pre(v); \ 38262306a36Sopenharmony_ci if (ret) \ 38362306a36Sopenharmony_ci return ret; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci#define TEST_PCPU(map) \ 38662306a36Sopenharmony_ci v = bpf_map_lookup_percpu_elem(&map, &key, 0); \ 38762306a36Sopenharmony_ci if (!v) \ 38862306a36Sopenharmony_ci return -1; \ 38962306a36Sopenharmony_ci ret = test_map_kptr_ref_pre(v); \ 39062306a36Sopenharmony_ci if (ret) \ 39162306a36Sopenharmony_ci return ret; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ciSEC("tc") 39462306a36Sopenharmony_ciint test_map_kptr_ref1(struct __sk_buff *ctx) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct map_value *v, val = {}; 39762306a36Sopenharmony_ci int key = 0, ret; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci bpf_map_update_elem(&hash_map, &key, &val, 0); 40062306a36Sopenharmony_ci bpf_map_update_elem(&hash_malloc_map, &key, &val, 0); 40162306a36Sopenharmony_ci bpf_map_update_elem(&lru_hash_map, &key, &val, 0); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci bpf_map_update_elem(&pcpu_hash_map, &key, &val, 0); 40462306a36Sopenharmony_ci bpf_map_update_elem(&pcpu_hash_malloc_map, &key, &val, 0); 40562306a36Sopenharmony_ci bpf_map_update_elem(&lru_pcpu_hash_map, &key, &val, 0); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci TEST(array_map); 40862306a36Sopenharmony_ci TEST(hash_map); 40962306a36Sopenharmony_ci TEST(hash_malloc_map); 41062306a36Sopenharmony_ci TEST(lru_hash_map); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci TEST_PCPU(pcpu_array_map); 41362306a36Sopenharmony_ci TEST_PCPU(pcpu_hash_map); 41462306a36Sopenharmony_ci TEST_PCPU(pcpu_hash_malloc_map); 41562306a36Sopenharmony_ci TEST_PCPU(lru_pcpu_hash_map); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci return 0; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci#undef TEST 42162306a36Sopenharmony_ci#undef TEST_PCPU 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci#define TEST(map) \ 42462306a36Sopenharmony_ci v = bpf_map_lookup_elem(&map, &key); \ 42562306a36Sopenharmony_ci if (!v) \ 42662306a36Sopenharmony_ci return -1; \ 42762306a36Sopenharmony_ci ret = test_map_kptr_ref_post(v); \ 42862306a36Sopenharmony_ci if (ret) \ 42962306a36Sopenharmony_ci return ret; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci#define TEST_PCPU(map) \ 43262306a36Sopenharmony_ci v = bpf_map_lookup_percpu_elem(&map, &key, 0); \ 43362306a36Sopenharmony_ci if (!v) \ 43462306a36Sopenharmony_ci return -1; \ 43562306a36Sopenharmony_ci ret = test_map_kptr_ref_post(v); \ 43662306a36Sopenharmony_ci if (ret) \ 43762306a36Sopenharmony_ci return ret; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ciSEC("tc") 44062306a36Sopenharmony_ciint test_map_kptr_ref2(struct __sk_buff *ctx) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci struct map_value *v; 44362306a36Sopenharmony_ci int key = 0, ret; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci TEST(array_map); 44662306a36Sopenharmony_ci TEST(hash_map); 44762306a36Sopenharmony_ci TEST(hash_malloc_map); 44862306a36Sopenharmony_ci TEST(lru_hash_map); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci TEST_PCPU(pcpu_array_map); 45162306a36Sopenharmony_ci TEST_PCPU(pcpu_hash_map); 45262306a36Sopenharmony_ci TEST_PCPU(pcpu_hash_malloc_map); 45362306a36Sopenharmony_ci TEST_PCPU(lru_pcpu_hash_map); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci return 0; 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci#undef TEST 45962306a36Sopenharmony_ci#undef TEST_PCPU 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ciSEC("tc") 46262306a36Sopenharmony_ciint test_map_kptr_ref3(struct __sk_buff *ctx) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci struct prog_test_ref_kfunc *p; 46562306a36Sopenharmony_ci unsigned long sp = 0; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci p = bpf_kfunc_call_test_acquire(&sp); 46862306a36Sopenharmony_ci if (!p) 46962306a36Sopenharmony_ci return 1; 47062306a36Sopenharmony_ci ref++; 47162306a36Sopenharmony_ci if (p->cnt.refs.counter != ref) { 47262306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 47362306a36Sopenharmony_ci return 2; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci bpf_kfunc_call_test_release(p); 47662306a36Sopenharmony_ci ref--; 47762306a36Sopenharmony_ci return 0; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ciSEC("syscall") 48162306a36Sopenharmony_ciint test_ls_map_kptr_ref1(void *ctx) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci struct task_struct *current; 48462306a36Sopenharmony_ci struct map_value *v; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci current = bpf_get_current_task_btf(); 48762306a36Sopenharmony_ci if (!current) 48862306a36Sopenharmony_ci return 100; 48962306a36Sopenharmony_ci v = bpf_task_storage_get(&task_ls_map, current, NULL, 0); 49062306a36Sopenharmony_ci if (v) 49162306a36Sopenharmony_ci return 150; 49262306a36Sopenharmony_ci v = bpf_task_storage_get(&task_ls_map, current, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE); 49362306a36Sopenharmony_ci if (!v) 49462306a36Sopenharmony_ci return 200; 49562306a36Sopenharmony_ci return test_map_kptr_ref_pre(v); 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ciSEC("syscall") 49962306a36Sopenharmony_ciint test_ls_map_kptr_ref2(void *ctx) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci struct task_struct *current; 50262306a36Sopenharmony_ci struct map_value *v; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci current = bpf_get_current_task_btf(); 50562306a36Sopenharmony_ci if (!current) 50662306a36Sopenharmony_ci return 100; 50762306a36Sopenharmony_ci v = bpf_task_storage_get(&task_ls_map, current, NULL, 0); 50862306a36Sopenharmony_ci if (!v) 50962306a36Sopenharmony_ci return 200; 51062306a36Sopenharmony_ci return test_map_kptr_ref_post(v); 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ciSEC("syscall") 51462306a36Sopenharmony_ciint test_ls_map_kptr_ref_del(void *ctx) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci struct task_struct *current; 51762306a36Sopenharmony_ci struct map_value *v; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci current = bpf_get_current_task_btf(); 52062306a36Sopenharmony_ci if (!current) 52162306a36Sopenharmony_ci return 100; 52262306a36Sopenharmony_ci v = bpf_task_storage_get(&task_ls_map, current, NULL, 0); 52362306a36Sopenharmony_ci if (!v) 52462306a36Sopenharmony_ci return 200; 52562306a36Sopenharmony_ci if (!v->ref_ptr) 52662306a36Sopenharmony_ci return 300; 52762306a36Sopenharmony_ci return bpf_task_storage_delete(&task_ls_map, current); 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 531