12cbc469aSKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0
22cbc469aSKumar Kartikeya Dwivedi #include <vmlinux.h>
32cbc469aSKumar Kartikeya Dwivedi #include <bpf/bpf_tracing.h>
42cbc469aSKumar Kartikeya Dwivedi #include <bpf/bpf_helpers.h>
52cbc469aSKumar Kartikeya Dwivedi #include "../bpf_testmod/bpf_testmod_kfunc.h"
62cbc469aSKumar Kartikeya Dwivedi
703b77e17SAlexei Starovoitov struct map_value {
803b77e17SAlexei Starovoitov struct prog_test_ref_kfunc __kptr_untrusted *unref_ptr;
92cbc469aSKumar Kartikeya Dwivedi struct prog_test_ref_kfunc __kptr *ref_ptr;
102cbc469aSKumar Kartikeya Dwivedi };
112cbc469aSKumar Kartikeya Dwivedi
122cbc469aSKumar Kartikeya Dwivedi struct array_map {
132cbc469aSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_ARRAY);
142cbc469aSKumar Kartikeya Dwivedi __type(key, int);
152cbc469aSKumar Kartikeya Dwivedi __type(value, struct map_value);
162cbc469aSKumar Kartikeya Dwivedi __uint(max_entries, 1);
172cbc469aSKumar Kartikeya Dwivedi } array_map SEC(".maps");
1885521e1eSKumar Kartikeya Dwivedi
1985521e1eSKumar Kartikeya Dwivedi struct pcpu_array_map {
2085521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
2185521e1eSKumar Kartikeya Dwivedi __type(key, int);
2285521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
2385521e1eSKumar Kartikeya Dwivedi __uint(max_entries, 1);
2485521e1eSKumar Kartikeya Dwivedi } pcpu_array_map SEC(".maps");
252cbc469aSKumar Kartikeya Dwivedi
262cbc469aSKumar Kartikeya Dwivedi struct hash_map {
272cbc469aSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_HASH);
282cbc469aSKumar Kartikeya Dwivedi __type(key, int);
292cbc469aSKumar Kartikeya Dwivedi __type(value, struct map_value);
302cbc469aSKumar Kartikeya Dwivedi __uint(max_entries, 1);
312cbc469aSKumar Kartikeya Dwivedi } hash_map SEC(".maps");
3285521e1eSKumar Kartikeya Dwivedi
3385521e1eSKumar Kartikeya Dwivedi struct pcpu_hash_map {
3485521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_PERCPU_HASH);
3585521e1eSKumar Kartikeya Dwivedi __type(key, int);
3685521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
3785521e1eSKumar Kartikeya Dwivedi __uint(max_entries, 1);
3885521e1eSKumar Kartikeya Dwivedi } pcpu_hash_map SEC(".maps");
392cbc469aSKumar Kartikeya Dwivedi
402cbc469aSKumar Kartikeya Dwivedi struct hash_malloc_map {
412cbc469aSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_HASH);
422cbc469aSKumar Kartikeya Dwivedi __type(key, int);
432cbc469aSKumar Kartikeya Dwivedi __type(value, struct map_value);
442cbc469aSKumar Kartikeya Dwivedi __uint(max_entries, 1);
452cbc469aSKumar Kartikeya Dwivedi __uint(map_flags, BPF_F_NO_PREALLOC);
462cbc469aSKumar Kartikeya Dwivedi } hash_malloc_map SEC(".maps");
4785521e1eSKumar Kartikeya Dwivedi
4885521e1eSKumar Kartikeya Dwivedi struct pcpu_hash_malloc_map {
4985521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_PERCPU_HASH);
5085521e1eSKumar Kartikeya Dwivedi __type(key, int);
5185521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
5285521e1eSKumar Kartikeya Dwivedi __uint(max_entries, 1);
5385521e1eSKumar Kartikeya Dwivedi __uint(map_flags, BPF_F_NO_PREALLOC);
5485521e1eSKumar Kartikeya Dwivedi } pcpu_hash_malloc_map SEC(".maps");
552cbc469aSKumar Kartikeya Dwivedi
562cbc469aSKumar Kartikeya Dwivedi struct lru_hash_map {
572cbc469aSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_LRU_HASH);
582cbc469aSKumar Kartikeya Dwivedi __type(key, int);
592cbc469aSKumar Kartikeya Dwivedi __type(value, struct map_value);
602cbc469aSKumar Kartikeya Dwivedi __uint(max_entries, 1);
612cbc469aSKumar Kartikeya Dwivedi } lru_hash_map SEC(".maps");
6285521e1eSKumar Kartikeya Dwivedi
6385521e1eSKumar Kartikeya Dwivedi struct lru_pcpu_hash_map {
6485521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_LRU_PERCPU_HASH);
6585521e1eSKumar Kartikeya Dwivedi __type(key, int);
6685521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
6785521e1eSKumar Kartikeya Dwivedi __uint(max_entries, 1);
6885521e1eSKumar Kartikeya Dwivedi } lru_pcpu_hash_map SEC(".maps");
6985521e1eSKumar Kartikeya Dwivedi
7085521e1eSKumar Kartikeya Dwivedi struct cgrp_ls_map {
7185521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_CGRP_STORAGE);
7285521e1eSKumar Kartikeya Dwivedi __uint(map_flags, BPF_F_NO_PREALLOC);
7385521e1eSKumar Kartikeya Dwivedi __type(key, int);
7485521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
7585521e1eSKumar Kartikeya Dwivedi } cgrp_ls_map SEC(".maps");
7685521e1eSKumar Kartikeya Dwivedi
7785521e1eSKumar Kartikeya Dwivedi struct task_ls_map {
7885521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_TASK_STORAGE);
7985521e1eSKumar Kartikeya Dwivedi __uint(map_flags, BPF_F_NO_PREALLOC);
8085521e1eSKumar Kartikeya Dwivedi __type(key, int);
8185521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
8285521e1eSKumar Kartikeya Dwivedi } task_ls_map SEC(".maps");
8385521e1eSKumar Kartikeya Dwivedi
8485521e1eSKumar Kartikeya Dwivedi struct inode_ls_map {
8585521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_INODE_STORAGE);
8685521e1eSKumar Kartikeya Dwivedi __uint(map_flags, BPF_F_NO_PREALLOC);
8785521e1eSKumar Kartikeya Dwivedi __type(key, int);
8885521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
8985521e1eSKumar Kartikeya Dwivedi } inode_ls_map SEC(".maps");
9085521e1eSKumar Kartikeya Dwivedi
9185521e1eSKumar Kartikeya Dwivedi struct sk_ls_map {
9285521e1eSKumar Kartikeya Dwivedi __uint(type, BPF_MAP_TYPE_SK_STORAGE);
9385521e1eSKumar Kartikeya Dwivedi __uint(map_flags, BPF_F_NO_PREALLOC);
9485521e1eSKumar Kartikeya Dwivedi __type(key, int);
9585521e1eSKumar Kartikeya Dwivedi __type(value, struct map_value);
9685521e1eSKumar Kartikeya Dwivedi } sk_ls_map SEC(".maps");
972cbc469aSKumar Kartikeya Dwivedi
982cbc469aSKumar Kartikeya Dwivedi #define DEFINE_MAP_OF_MAP(map_type, inner_map_type, name) \
992cbc469aSKumar Kartikeya Dwivedi struct { \
1002cbc469aSKumar Kartikeya Dwivedi __uint(type, map_type); \
1012cbc469aSKumar Kartikeya Dwivedi __uint(max_entries, 1); \
1022cbc469aSKumar Kartikeya Dwivedi __uint(key_size, sizeof(int)); \
1032cbc469aSKumar Kartikeya Dwivedi __uint(value_size, sizeof(int)); \
1042cbc469aSKumar Kartikeya Dwivedi __array(values, struct inner_map_type); \
1052cbc469aSKumar Kartikeya Dwivedi } name SEC(".maps") = { \
1062cbc469aSKumar Kartikeya Dwivedi .values = { [0] = &inner_map_type }, \
1072cbc469aSKumar Kartikeya Dwivedi }
1082cbc469aSKumar Kartikeya Dwivedi
1092cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_map, array_of_array_maps);
1102cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_map, array_of_hash_maps);
1112cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_malloc_map, array_of_hash_malloc_maps);
1122cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, lru_hash_map, array_of_lru_hash_maps);
1132cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, array_map, hash_of_array_maps);
1142cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_map, hash_of_hash_maps);
1152cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_malloc_map, hash_of_hash_malloc_maps);
1162cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, lru_hash_map, hash_of_lru_hash_maps);
1172cbc469aSKumar Kartikeya Dwivedi
1182cbc469aSKumar Kartikeya Dwivedi #define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val))
119838bd4acSAlexei Starovoitov
test_kptr_unref(struct map_value * v)1202cbc469aSKumar Kartikeya Dwivedi static void test_kptr_unref(struct map_value *v)
12162d101d5SAlexei Starovoitov {
12262d101d5SAlexei Starovoitov struct prog_test_ref_kfunc *p;
1232cbc469aSKumar Kartikeya Dwivedi
1242cbc469aSKumar Kartikeya Dwivedi p = v->unref_ptr;
1252cbc469aSKumar Kartikeya Dwivedi /* store untrusted_ptr_or_null_ */
1262cbc469aSKumar Kartikeya Dwivedi WRITE_ONCE(v->unref_ptr, p);
1272cbc469aSKumar Kartikeya Dwivedi if (!p)
1282cbc469aSKumar Kartikeya Dwivedi return;
12962d101d5SAlexei Starovoitov if (p->a + p->b > 100)
1302cbc469aSKumar Kartikeya Dwivedi return;
1312cbc469aSKumar Kartikeya Dwivedi /* store untrusted_ptr_ */
1322cbc469aSKumar Kartikeya Dwivedi WRITE_ONCE(v->unref_ptr, p);
1332cbc469aSKumar Kartikeya Dwivedi /* store NULL */
1342cbc469aSKumar Kartikeya Dwivedi WRITE_ONCE(v->unref_ptr, NULL);
13562d101d5SAlexei Starovoitov }
1362cbc469aSKumar Kartikeya Dwivedi
test_kptr_ref(struct map_value * v)13762d101d5SAlexei Starovoitov static void test_kptr_ref(struct map_value *v)
1382cbc469aSKumar Kartikeya Dwivedi {
1392cbc469aSKumar Kartikeya Dwivedi struct prog_test_ref_kfunc *p;
1402cbc469aSKumar Kartikeya Dwivedi
1412cbc469aSKumar Kartikeya Dwivedi p = v->ref_ptr;
1422cbc469aSKumar Kartikeya Dwivedi /* store ptr_or_null_ */
1432cbc469aSKumar Kartikeya Dwivedi WRITE_ONCE(v->unref_ptr, p);
1442cbc469aSKumar Kartikeya Dwivedi if (!p)
1452cbc469aSKumar Kartikeya Dwivedi return;
14662d101d5SAlexei Starovoitov /*
1472cbc469aSKumar Kartikeya Dwivedi * p is rcu_ptr_prog_test_ref_kfunc,
1482cbc469aSKumar Kartikeya Dwivedi * because bpf prog is non-sleepable and runs in RCU CS.
149838bd4acSAlexei Starovoitov * p can be passed to kfunc that requires KF_RCU.
150838bd4acSAlexei Starovoitov */
151838bd4acSAlexei Starovoitov bpf_kfunc_call_test_ref(p);
152838bd4acSAlexei Starovoitov if (p->a + p->b > 100)
153838bd4acSAlexei Starovoitov return;
154838bd4acSAlexei Starovoitov /* store NULL */
1552cbc469aSKumar Kartikeya Dwivedi p = bpf_kptr_xchg(&v->ref_ptr, NULL);
1562cbc469aSKumar Kartikeya Dwivedi if (!p)
1572cbc469aSKumar Kartikeya Dwivedi return;
1582cbc469aSKumar Kartikeya Dwivedi /*
1592cbc469aSKumar Kartikeya Dwivedi * p is trusted_ptr_prog_test_ref_kfunc.
1602cbc469aSKumar Kartikeya Dwivedi * p can be passed to kfunc that requires KF_RCU.
161838bd4acSAlexei Starovoitov */
162838bd4acSAlexei Starovoitov bpf_kfunc_call_test_ref(p);
163838bd4acSAlexei Starovoitov if (p->a + p->b > 100) {
164838bd4acSAlexei Starovoitov bpf_kfunc_call_test_release(p);
165838bd4acSAlexei Starovoitov return;
1662cbc469aSKumar Kartikeya Dwivedi }
1672cbc469aSKumar Kartikeya Dwivedi /* store ptr_ */
1682cbc469aSKumar Kartikeya Dwivedi WRITE_ONCE(v->unref_ptr, p);
1692cbc469aSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
1702cbc469aSKumar Kartikeya Dwivedi
17162d101d5SAlexei Starovoitov p = bpf_kfunc_call_test_acquire(&(unsigned long){0});
1722cbc469aSKumar Kartikeya Dwivedi if (!p)
1732cbc469aSKumar Kartikeya Dwivedi return;
1742cbc469aSKumar Kartikeya Dwivedi /* store ptr_ */
1752cbc469aSKumar Kartikeya Dwivedi p = bpf_kptr_xchg(&v->ref_ptr, p);
1762cbc469aSKumar Kartikeya Dwivedi if (!p)
1772cbc469aSKumar Kartikeya Dwivedi return;
1782cbc469aSKumar Kartikeya Dwivedi if (p->a + p->b > 100) {
1792cbc469aSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
1802cbc469aSKumar Kartikeya Dwivedi return;
1812cbc469aSKumar Kartikeya Dwivedi }
1822cbc469aSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
1832cbc469aSKumar Kartikeya Dwivedi }
1842cbc469aSKumar Kartikeya Dwivedi
test_kptr(struct map_value * v)1852cbc469aSKumar Kartikeya Dwivedi static void test_kptr(struct map_value *v)
1862cbc469aSKumar Kartikeya Dwivedi {
1872cbc469aSKumar Kartikeya Dwivedi test_kptr_unref(v);
1882cbc469aSKumar Kartikeya Dwivedi test_kptr_ref(v);
1892cbc469aSKumar Kartikeya Dwivedi }
1902cbc469aSKumar Kartikeya Dwivedi
1912cbc469aSKumar Kartikeya Dwivedi SEC("tc")
test_map_kptr(struct __sk_buff * ctx)1922cbc469aSKumar Kartikeya Dwivedi int test_map_kptr(struct __sk_buff *ctx)
1932cbc469aSKumar Kartikeya Dwivedi {
1942cbc469aSKumar Kartikeya Dwivedi struct map_value *v;
1952cbc469aSKumar Kartikeya Dwivedi int key = 0;
1962cbc469aSKumar Kartikeya Dwivedi
1972cbc469aSKumar Kartikeya Dwivedi #define TEST(map) \
1980ef6740eSKumar Kartikeya Dwivedi v = bpf_map_lookup_elem(&map, &key); \
1992cbc469aSKumar Kartikeya Dwivedi if (!v) \
2002cbc469aSKumar Kartikeya Dwivedi return 0; \
2012cbc469aSKumar Kartikeya Dwivedi test_kptr(v)
2022cbc469aSKumar Kartikeya Dwivedi
2032cbc469aSKumar Kartikeya Dwivedi TEST(array_map);
2042cbc469aSKumar Kartikeya Dwivedi TEST(hash_map);
2052cbc469aSKumar Kartikeya Dwivedi TEST(hash_malloc_map);
2062cbc469aSKumar Kartikeya Dwivedi TEST(lru_hash_map);
2072cbc469aSKumar Kartikeya Dwivedi
2082cbc469aSKumar Kartikeya Dwivedi #undef TEST
2092cbc469aSKumar Kartikeya Dwivedi return 0;
2102cbc469aSKumar Kartikeya Dwivedi }
2112cbc469aSKumar Kartikeya Dwivedi
2122cbc469aSKumar Kartikeya Dwivedi SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_map_kptr,struct cgroup * cgrp,const char * path)2132cbc469aSKumar Kartikeya Dwivedi int BPF_PROG(test_cgrp_map_kptr, struct cgroup *cgrp, const char *path)
2142cbc469aSKumar Kartikeya Dwivedi {
21585521e1eSKumar Kartikeya Dwivedi struct map_value *v;
21685521e1eSKumar Kartikeya Dwivedi
21785521e1eSKumar Kartikeya Dwivedi v = bpf_cgrp_storage_get(&cgrp_ls_map, cgrp, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
21885521e1eSKumar Kartikeya Dwivedi if (v)
21985521e1eSKumar Kartikeya Dwivedi test_kptr(v);
22085521e1eSKumar Kartikeya Dwivedi return 0;
22185521e1eSKumar Kartikeya Dwivedi }
22285521e1eSKumar Kartikeya Dwivedi
22385521e1eSKumar Kartikeya Dwivedi SEC("lsm/inode_unlink")
BPF_PROG(test_task_map_kptr,struct inode * inode,struct dentry * victim)22485521e1eSKumar Kartikeya Dwivedi int BPF_PROG(test_task_map_kptr, struct inode *inode, struct dentry *victim)
22585521e1eSKumar Kartikeya Dwivedi {
22685521e1eSKumar Kartikeya Dwivedi struct task_struct *task;
22785521e1eSKumar Kartikeya Dwivedi struct map_value *v;
22885521e1eSKumar Kartikeya Dwivedi
22985521e1eSKumar Kartikeya Dwivedi task = bpf_get_current_task_btf();
23085521e1eSKumar Kartikeya Dwivedi if (!task)
23185521e1eSKumar Kartikeya Dwivedi return 0;
23285521e1eSKumar Kartikeya Dwivedi v = bpf_task_storage_get(&task_ls_map, task, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
23385521e1eSKumar Kartikeya Dwivedi if (v)
23485521e1eSKumar Kartikeya Dwivedi test_kptr(v);
23585521e1eSKumar Kartikeya Dwivedi return 0;
23685521e1eSKumar Kartikeya Dwivedi }
23785521e1eSKumar Kartikeya Dwivedi
23885521e1eSKumar Kartikeya Dwivedi SEC("lsm/inode_unlink")
BPF_PROG(test_inode_map_kptr,struct inode * inode,struct dentry * victim)23985521e1eSKumar Kartikeya Dwivedi int BPF_PROG(test_inode_map_kptr, struct inode *inode, struct dentry *victim)
24085521e1eSKumar Kartikeya Dwivedi {
24185521e1eSKumar Kartikeya Dwivedi struct map_value *v;
24285521e1eSKumar Kartikeya Dwivedi
24385521e1eSKumar Kartikeya Dwivedi v = bpf_inode_storage_get(&inode_ls_map, inode, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
24485521e1eSKumar Kartikeya Dwivedi if (v)
24585521e1eSKumar Kartikeya Dwivedi test_kptr(v);
24685521e1eSKumar Kartikeya Dwivedi return 0;
24785521e1eSKumar Kartikeya Dwivedi }
24885521e1eSKumar Kartikeya Dwivedi
24985521e1eSKumar Kartikeya Dwivedi SEC("tc")
test_sk_map_kptr(struct __sk_buff * ctx)25085521e1eSKumar Kartikeya Dwivedi int test_sk_map_kptr(struct __sk_buff *ctx)
25185521e1eSKumar Kartikeya Dwivedi {
25285521e1eSKumar Kartikeya Dwivedi struct map_value *v;
25385521e1eSKumar Kartikeya Dwivedi struct bpf_sock *sk;
25485521e1eSKumar Kartikeya Dwivedi
25585521e1eSKumar Kartikeya Dwivedi sk = ctx->sk;
25685521e1eSKumar Kartikeya Dwivedi if (!sk)
25785521e1eSKumar Kartikeya Dwivedi return 0;
25885521e1eSKumar Kartikeya Dwivedi v = bpf_sk_storage_get(&sk_ls_map, sk, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
25985521e1eSKumar Kartikeya Dwivedi if (v)
26085521e1eSKumar Kartikeya Dwivedi test_kptr(v);
26185521e1eSKumar Kartikeya Dwivedi return 0;
26285521e1eSKumar Kartikeya Dwivedi }
26385521e1eSKumar Kartikeya Dwivedi
26485521e1eSKumar Kartikeya Dwivedi SEC("tc")
test_map_in_map_kptr(struct __sk_buff * ctx)26585521e1eSKumar Kartikeya Dwivedi int test_map_in_map_kptr(struct __sk_buff *ctx)
26685521e1eSKumar Kartikeya Dwivedi {
2672cbc469aSKumar Kartikeya Dwivedi struct map_value *v;
2682cbc469aSKumar Kartikeya Dwivedi int key = 0;
2692cbc469aSKumar Kartikeya Dwivedi void *map;
2702cbc469aSKumar Kartikeya Dwivedi
2710ef6740eSKumar Kartikeya Dwivedi #define TEST(map_in_map) \
2722cbc469aSKumar Kartikeya Dwivedi map = bpf_map_lookup_elem(&map_in_map, &key); \
2732cbc469aSKumar Kartikeya Dwivedi if (!map) \
2742cbc469aSKumar Kartikeya Dwivedi return 0; \
2752cbc469aSKumar Kartikeya Dwivedi v = bpf_map_lookup_elem(map, &key); \
2762cbc469aSKumar Kartikeya Dwivedi if (!v) \
2772cbc469aSKumar Kartikeya Dwivedi return 0; \
2782cbc469aSKumar Kartikeya Dwivedi test_kptr(v)
2792cbc469aSKumar Kartikeya Dwivedi
2802cbc469aSKumar Kartikeya Dwivedi TEST(array_of_array_maps);
2812cbc469aSKumar Kartikeya Dwivedi TEST(array_of_hash_maps);
2822cbc469aSKumar Kartikeya Dwivedi TEST(array_of_hash_malloc_maps);
2832cbc469aSKumar Kartikeya Dwivedi TEST(array_of_lru_hash_maps);
2842cbc469aSKumar Kartikeya Dwivedi TEST(hash_of_array_maps);
2852cbc469aSKumar Kartikeya Dwivedi TEST(hash_of_hash_maps);
2862cbc469aSKumar Kartikeya Dwivedi TEST(hash_of_hash_malloc_maps);
2872cbc469aSKumar Kartikeya Dwivedi TEST(hash_of_lru_hash_maps);
2882cbc469aSKumar Kartikeya Dwivedi
2892cbc469aSKumar Kartikeya Dwivedi #undef TEST
2902cbc469aSKumar Kartikeya Dwivedi return 0;
2912cbc469aSKumar Kartikeya Dwivedi }
2922cbc469aSKumar Kartikeya Dwivedi
2932cbc469aSKumar Kartikeya Dwivedi int ref = 1;
2942cbc469aSKumar Kartikeya Dwivedi
2952cbc469aSKumar Kartikeya Dwivedi static __always_inline
test_map_kptr_ref_pre(struct map_value * v)29685521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref_pre(struct map_value *v)
29785521e1eSKumar Kartikeya Dwivedi {
29885521e1eSKumar Kartikeya Dwivedi struct prog_test_ref_kfunc *p, *p_st;
29985521e1eSKumar Kartikeya Dwivedi unsigned long arg = 0;
3000ef6740eSKumar Kartikeya Dwivedi int ret;
3010ef6740eSKumar Kartikeya Dwivedi
3020ef6740eSKumar Kartikeya Dwivedi p = bpf_kfunc_call_test_acquire(&arg);
30385521e1eSKumar Kartikeya Dwivedi if (!p)
3040ef6740eSKumar Kartikeya Dwivedi return 1;
3050ef6740eSKumar Kartikeya Dwivedi ref++;
3060ef6740eSKumar Kartikeya Dwivedi
3070ef6740eSKumar Kartikeya Dwivedi p_st = p->next;
30885521e1eSKumar Kartikeya Dwivedi if (p_st->cnt.refs.counter != ref) {
3090ef6740eSKumar Kartikeya Dwivedi ret = 2;
3100ef6740eSKumar Kartikeya Dwivedi goto end;
31185521e1eSKumar Kartikeya Dwivedi }
3120ef6740eSKumar Kartikeya Dwivedi
3130ef6740eSKumar Kartikeya Dwivedi p = bpf_kptr_xchg(&v->ref_ptr, p);
3140ef6740eSKumar Kartikeya Dwivedi if (p) {
3150ef6740eSKumar Kartikeya Dwivedi ret = 3;
31685521e1eSKumar Kartikeya Dwivedi goto end;
31785521e1eSKumar Kartikeya Dwivedi }
3180ef6740eSKumar Kartikeya Dwivedi if (p_st->cnt.refs.counter != ref)
3190ef6740eSKumar Kartikeya Dwivedi return 4;
3200ef6740eSKumar Kartikeya Dwivedi
32185521e1eSKumar Kartikeya Dwivedi p = bpf_kptr_xchg(&v->ref_ptr, NULL);
32285521e1eSKumar Kartikeya Dwivedi if (!p)
3230ef6740eSKumar Kartikeya Dwivedi return 5;
3240ef6740eSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
3250ef6740eSKumar Kartikeya Dwivedi ref--;
326*09b501d9SDavid Vernet if (p_st->cnt.refs.counter != ref)
3270ef6740eSKumar Kartikeya Dwivedi return 6;
32885521e1eSKumar Kartikeya Dwivedi
32985521e1eSKumar Kartikeya Dwivedi p = bpf_kfunc_call_test_acquire(&arg);
330*09b501d9SDavid Vernet if (!p)
3310ef6740eSKumar Kartikeya Dwivedi return 7;
3320ef6740eSKumar Kartikeya Dwivedi ref++;
3330ef6740eSKumar Kartikeya Dwivedi p = bpf_kptr_xchg(&v->ref_ptr, p);
334*09b501d9SDavid Vernet if (p) {
33585521e1eSKumar Kartikeya Dwivedi ret = 8;
3360ef6740eSKumar Kartikeya Dwivedi goto end;
3370ef6740eSKumar Kartikeya Dwivedi }
338*09b501d9SDavid Vernet if (p_st->cnt.refs.counter != ref)
3390ef6740eSKumar Kartikeya Dwivedi return 9;
3400ef6740eSKumar Kartikeya Dwivedi /* Leave in map */
34185521e1eSKumar Kartikeya Dwivedi
342*09b501d9SDavid Vernet return 0;
3430ef6740eSKumar Kartikeya Dwivedi end:
3440ef6740eSKumar Kartikeya Dwivedi ref--;
3450ef6740eSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
3460ef6740eSKumar Kartikeya Dwivedi return ret;
34785521e1eSKumar Kartikeya Dwivedi }
3480ef6740eSKumar Kartikeya Dwivedi
3490ef6740eSKumar Kartikeya Dwivedi static __always_inline
test_map_kptr_ref_post(struct map_value * v)3500ef6740eSKumar Kartikeya Dwivedi int test_map_kptr_ref_post(struct map_value *v)
3510ef6740eSKumar Kartikeya Dwivedi {
35285521e1eSKumar Kartikeya Dwivedi struct prog_test_ref_kfunc *p, *p_st;
35385521e1eSKumar Kartikeya Dwivedi
3540ef6740eSKumar Kartikeya Dwivedi p_st = v->ref_ptr;
3550ef6740eSKumar Kartikeya Dwivedi if (!p_st || p_st->cnt.refs.counter != ref)
3560ef6740eSKumar Kartikeya Dwivedi return 1;
3570ef6740eSKumar Kartikeya Dwivedi
35885521e1eSKumar Kartikeya Dwivedi p = bpf_kptr_xchg(&v->ref_ptr, NULL);
35985521e1eSKumar Kartikeya Dwivedi if (!p)
3600ef6740eSKumar Kartikeya Dwivedi return 2;
3610ef6740eSKumar Kartikeya Dwivedi if (p_st->cnt.refs.counter != ref) {
3620ef6740eSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
36385521e1eSKumar Kartikeya Dwivedi return 3;
36485521e1eSKumar Kartikeya Dwivedi }
3650ef6740eSKumar Kartikeya Dwivedi
36685521e1eSKumar Kartikeya Dwivedi p = bpf_kptr_xchg(&v->ref_ptr, p);
3670ef6740eSKumar Kartikeya Dwivedi if (p) {
3680ef6740eSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
3690ef6740eSKumar Kartikeya Dwivedi return 4;
3700ef6740eSKumar Kartikeya Dwivedi }
3710ef6740eSKumar Kartikeya Dwivedi if (p_st->cnt.refs.counter != ref)
37285521e1eSKumar Kartikeya Dwivedi return 5;
3730ef6740eSKumar Kartikeya Dwivedi
37485521e1eSKumar Kartikeya Dwivedi return 0;
37585521e1eSKumar Kartikeya Dwivedi }
3760ef6740eSKumar Kartikeya Dwivedi
3770ef6740eSKumar Kartikeya Dwivedi #define TEST(map) \
3780ef6740eSKumar Kartikeya Dwivedi v = bpf_map_lookup_elem(&map, &key); \
3790ef6740eSKumar Kartikeya Dwivedi if (!v) \
38085521e1eSKumar Kartikeya Dwivedi return -1; \
38185521e1eSKumar Kartikeya Dwivedi ret = test_map_kptr_ref_pre(v); \
38285521e1eSKumar Kartikeya Dwivedi if (ret) \
38385521e1eSKumar Kartikeya Dwivedi return ret;
38485521e1eSKumar Kartikeya Dwivedi
38585521e1eSKumar Kartikeya Dwivedi #define TEST_PCPU(map) \
38685521e1eSKumar Kartikeya Dwivedi v = bpf_map_lookup_percpu_elem(&map, &key, 0); \
38785521e1eSKumar Kartikeya Dwivedi if (!v) \
38885521e1eSKumar Kartikeya Dwivedi return -1; \
38985521e1eSKumar Kartikeya Dwivedi ret = test_map_kptr_ref_pre(v); \
39085521e1eSKumar Kartikeya Dwivedi if (ret) \
39185521e1eSKumar Kartikeya Dwivedi return ret;
39285521e1eSKumar Kartikeya Dwivedi
39385521e1eSKumar Kartikeya Dwivedi SEC("tc")
test_map_kptr_ref1(struct __sk_buff * ctx)39485521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref1(struct __sk_buff *ctx)
39585521e1eSKumar Kartikeya Dwivedi {
39685521e1eSKumar Kartikeya Dwivedi struct map_value *v, val = {};
39785521e1eSKumar Kartikeya Dwivedi int key = 0, ret;
39885521e1eSKumar Kartikeya Dwivedi
39985521e1eSKumar Kartikeya Dwivedi bpf_map_update_elem(&hash_map, &key, &val, 0);
40085521e1eSKumar Kartikeya Dwivedi bpf_map_update_elem(&hash_malloc_map, &key, &val, 0);
40185521e1eSKumar Kartikeya Dwivedi bpf_map_update_elem(&lru_hash_map, &key, &val, 0);
40285521e1eSKumar Kartikeya Dwivedi
40385521e1eSKumar Kartikeya Dwivedi bpf_map_update_elem(&pcpu_hash_map, &key, &val, 0);
40485521e1eSKumar Kartikeya Dwivedi bpf_map_update_elem(&pcpu_hash_malloc_map, &key, &val, 0);
40585521e1eSKumar Kartikeya Dwivedi bpf_map_update_elem(&lru_pcpu_hash_map, &key, &val, 0);
40685521e1eSKumar Kartikeya Dwivedi
40785521e1eSKumar Kartikeya Dwivedi TEST(array_map);
40885521e1eSKumar Kartikeya Dwivedi TEST(hash_map);
40985521e1eSKumar Kartikeya Dwivedi TEST(hash_malloc_map);
41085521e1eSKumar Kartikeya Dwivedi TEST(lru_hash_map);
41185521e1eSKumar Kartikeya Dwivedi
41285521e1eSKumar Kartikeya Dwivedi TEST_PCPU(pcpu_array_map);
41385521e1eSKumar Kartikeya Dwivedi TEST_PCPU(pcpu_hash_map);
41485521e1eSKumar Kartikeya Dwivedi TEST_PCPU(pcpu_hash_malloc_map);
41585521e1eSKumar Kartikeya Dwivedi TEST_PCPU(lru_pcpu_hash_map);
41685521e1eSKumar Kartikeya Dwivedi
41785521e1eSKumar Kartikeya Dwivedi return 0;
41885521e1eSKumar Kartikeya Dwivedi }
41985521e1eSKumar Kartikeya Dwivedi
42085521e1eSKumar Kartikeya Dwivedi #undef TEST
42185521e1eSKumar Kartikeya Dwivedi #undef TEST_PCPU
42285521e1eSKumar Kartikeya Dwivedi
42385521e1eSKumar Kartikeya Dwivedi #define TEST(map) \
42485521e1eSKumar Kartikeya Dwivedi v = bpf_map_lookup_elem(&map, &key); \
42585521e1eSKumar Kartikeya Dwivedi if (!v) \
42685521e1eSKumar Kartikeya Dwivedi return -1; \
42785521e1eSKumar Kartikeya Dwivedi ret = test_map_kptr_ref_post(v); \
42885521e1eSKumar Kartikeya Dwivedi if (ret) \
42985521e1eSKumar Kartikeya Dwivedi return ret;
43085521e1eSKumar Kartikeya Dwivedi
43185521e1eSKumar Kartikeya Dwivedi #define TEST_PCPU(map) \
43285521e1eSKumar Kartikeya Dwivedi v = bpf_map_lookup_percpu_elem(&map, &key, 0); \
43385521e1eSKumar Kartikeya Dwivedi if (!v) \
43485521e1eSKumar Kartikeya Dwivedi return -1; \
43585521e1eSKumar Kartikeya Dwivedi ret = test_map_kptr_ref_post(v); \
43685521e1eSKumar Kartikeya Dwivedi if (ret) \
43785521e1eSKumar Kartikeya Dwivedi return ret;
43885521e1eSKumar Kartikeya Dwivedi
43985521e1eSKumar Kartikeya Dwivedi SEC("tc")
test_map_kptr_ref2(struct __sk_buff * ctx)44085521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref2(struct __sk_buff *ctx)
44185521e1eSKumar Kartikeya Dwivedi {
44285521e1eSKumar Kartikeya Dwivedi struct map_value *v;
44385521e1eSKumar Kartikeya Dwivedi int key = 0, ret;
44485521e1eSKumar Kartikeya Dwivedi
44585521e1eSKumar Kartikeya Dwivedi TEST(array_map);
44685521e1eSKumar Kartikeya Dwivedi TEST(hash_map);
44785521e1eSKumar Kartikeya Dwivedi TEST(hash_malloc_map);
44885521e1eSKumar Kartikeya Dwivedi TEST(lru_hash_map);
44985521e1eSKumar Kartikeya Dwivedi
45085521e1eSKumar Kartikeya Dwivedi TEST_PCPU(pcpu_array_map);
45185521e1eSKumar Kartikeya Dwivedi TEST_PCPU(pcpu_hash_map);
45285521e1eSKumar Kartikeya Dwivedi TEST_PCPU(pcpu_hash_malloc_map);
45385521e1eSKumar Kartikeya Dwivedi TEST_PCPU(lru_pcpu_hash_map);
45485521e1eSKumar Kartikeya Dwivedi
45585521e1eSKumar Kartikeya Dwivedi return 0;
45685521e1eSKumar Kartikeya Dwivedi }
45785521e1eSKumar Kartikeya Dwivedi
45885521e1eSKumar Kartikeya Dwivedi #undef TEST
45985521e1eSKumar Kartikeya Dwivedi #undef TEST_PCPU
46085521e1eSKumar Kartikeya Dwivedi
46185521e1eSKumar Kartikeya Dwivedi SEC("tc")
test_map_kptr_ref3(struct __sk_buff * ctx)46285521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref3(struct __sk_buff *ctx)
46385521e1eSKumar Kartikeya Dwivedi {
46485521e1eSKumar Kartikeya Dwivedi struct prog_test_ref_kfunc *p;
46585521e1eSKumar Kartikeya Dwivedi unsigned long sp = 0;
46685521e1eSKumar Kartikeya Dwivedi
46785521e1eSKumar Kartikeya Dwivedi p = bpf_kfunc_call_test_acquire(&sp);
46885521e1eSKumar Kartikeya Dwivedi if (!p)
46985521e1eSKumar Kartikeya Dwivedi return 1;
47085521e1eSKumar Kartikeya Dwivedi ref++;
47185521e1eSKumar Kartikeya Dwivedi if (p->cnt.refs.counter != ref) {
47285521e1eSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
47385521e1eSKumar Kartikeya Dwivedi return 2;
47485521e1eSKumar Kartikeya Dwivedi }
47585521e1eSKumar Kartikeya Dwivedi bpf_kfunc_call_test_release(p);
47685521e1eSKumar Kartikeya Dwivedi ref--;
47785521e1eSKumar Kartikeya Dwivedi return 0;
47885521e1eSKumar Kartikeya Dwivedi }
47985521e1eSKumar Kartikeya Dwivedi
48085521e1eSKumar Kartikeya Dwivedi SEC("syscall")
test_ls_map_kptr_ref1(void * ctx)48185521e1eSKumar Kartikeya Dwivedi int test_ls_map_kptr_ref1(void *ctx)
48285521e1eSKumar Kartikeya Dwivedi {
48385521e1eSKumar Kartikeya Dwivedi struct task_struct *current;
48485521e1eSKumar Kartikeya Dwivedi struct map_value *v;
48585521e1eSKumar Kartikeya Dwivedi
48685521e1eSKumar Kartikeya Dwivedi current = bpf_get_current_task_btf();
48785521e1eSKumar Kartikeya Dwivedi if (!current)
48885521e1eSKumar Kartikeya Dwivedi return 100;
48985521e1eSKumar Kartikeya Dwivedi v = bpf_task_storage_get(&task_ls_map, current, NULL, 0);
49085521e1eSKumar Kartikeya Dwivedi if (v)
49185521e1eSKumar Kartikeya Dwivedi return 150;
49285521e1eSKumar Kartikeya Dwivedi v = bpf_task_storage_get(&task_ls_map, current, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
49385521e1eSKumar Kartikeya Dwivedi if (!v)
49485521e1eSKumar Kartikeya Dwivedi return 200;
49585521e1eSKumar Kartikeya Dwivedi return test_map_kptr_ref_pre(v);
49685521e1eSKumar Kartikeya Dwivedi }
49785521e1eSKumar Kartikeya Dwivedi
49885521e1eSKumar Kartikeya Dwivedi SEC("syscall")
test_ls_map_kptr_ref2(void * ctx)49985521e1eSKumar Kartikeya Dwivedi int test_ls_map_kptr_ref2(void *ctx)
50085521e1eSKumar Kartikeya Dwivedi {
50185521e1eSKumar Kartikeya Dwivedi struct task_struct *current;
50285521e1eSKumar Kartikeya Dwivedi struct map_value *v;
50385521e1eSKumar Kartikeya Dwivedi
50485521e1eSKumar Kartikeya Dwivedi current = bpf_get_current_task_btf();
50585521e1eSKumar Kartikeya Dwivedi if (!current)
50685521e1eSKumar Kartikeya Dwivedi return 100;
50785521e1eSKumar Kartikeya Dwivedi v = bpf_task_storage_get(&task_ls_map, current, NULL, 0);
50885521e1eSKumar Kartikeya Dwivedi if (!v)
50985521e1eSKumar Kartikeya Dwivedi return 200;
51085521e1eSKumar Kartikeya Dwivedi return test_map_kptr_ref_post(v);
51185521e1eSKumar Kartikeya Dwivedi }
51285521e1eSKumar Kartikeya Dwivedi
51385521e1eSKumar Kartikeya Dwivedi SEC("syscall")
test_ls_map_kptr_ref_del(void * ctx)51485521e1eSKumar Kartikeya Dwivedi int test_ls_map_kptr_ref_del(void *ctx)
51585521e1eSKumar Kartikeya Dwivedi {
51685521e1eSKumar Kartikeya Dwivedi struct task_struct *current;
51785521e1eSKumar Kartikeya Dwivedi struct map_value *v;
51885521e1eSKumar Kartikeya Dwivedi
51985521e1eSKumar Kartikeya Dwivedi current = bpf_get_current_task_btf();
52085521e1eSKumar Kartikeya Dwivedi if (!current)
52185521e1eSKumar Kartikeya Dwivedi return 100;
52285521e1eSKumar Kartikeya Dwivedi v = bpf_task_storage_get(&task_ls_map, current, NULL, 0);
52385521e1eSKumar Kartikeya Dwivedi if (!v)
52485521e1eSKumar Kartikeya Dwivedi return 200;
52585521e1eSKumar Kartikeya Dwivedi if (!v->ref_ptr)
52685521e1eSKumar Kartikeya Dwivedi return 300;
52785521e1eSKumar Kartikeya Dwivedi return bpf_task_storage_delete(&task_ls_map, current);
52885521e1eSKumar Kartikeya Dwivedi }
52985521e1eSKumar Kartikeya Dwivedi
53085521e1eSKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
53185521e1eSKumar Kartikeya Dwivedi