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 
62cbc469aSKumar Kartikeya Dwivedi struct map_value {
7*03b77e17SAlexei Starovoitov 	struct prog_test_ref_kfunc __kptr_untrusted *unref_ptr;
8*03b77e17SAlexei Starovoitov 	struct prog_test_ref_kfunc __kptr *ref_ptr;
92cbc469aSKumar Kartikeya Dwivedi };
102cbc469aSKumar Kartikeya Dwivedi 
112cbc469aSKumar Kartikeya Dwivedi struct array_map {
122cbc469aSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_ARRAY);
132cbc469aSKumar Kartikeya Dwivedi 	__type(key, int);
142cbc469aSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
152cbc469aSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
162cbc469aSKumar Kartikeya Dwivedi } array_map SEC(".maps");
172cbc469aSKumar Kartikeya Dwivedi 
1885521e1eSKumar Kartikeya Dwivedi struct pcpu_array_map {
1985521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
2085521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
2185521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
2285521e1eSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
2385521e1eSKumar Kartikeya Dwivedi } pcpu_array_map SEC(".maps");
2485521e1eSKumar Kartikeya Dwivedi 
252cbc469aSKumar Kartikeya Dwivedi struct hash_map {
262cbc469aSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_HASH);
272cbc469aSKumar Kartikeya Dwivedi 	__type(key, int);
282cbc469aSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
292cbc469aSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
302cbc469aSKumar Kartikeya Dwivedi } hash_map SEC(".maps");
312cbc469aSKumar Kartikeya Dwivedi 
3285521e1eSKumar Kartikeya Dwivedi struct pcpu_hash_map {
3385521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
3485521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
3585521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
3685521e1eSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
3785521e1eSKumar Kartikeya Dwivedi } pcpu_hash_map SEC(".maps");
3885521e1eSKumar Kartikeya Dwivedi 
392cbc469aSKumar Kartikeya Dwivedi struct hash_malloc_map {
402cbc469aSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_HASH);
412cbc469aSKumar Kartikeya Dwivedi 	__type(key, int);
422cbc469aSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
432cbc469aSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
442cbc469aSKumar Kartikeya Dwivedi 	__uint(map_flags, BPF_F_NO_PREALLOC);
452cbc469aSKumar Kartikeya Dwivedi } hash_malloc_map SEC(".maps");
462cbc469aSKumar Kartikeya Dwivedi 
4785521e1eSKumar Kartikeya Dwivedi struct pcpu_hash_malloc_map {
4885521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
4985521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
5085521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
5185521e1eSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
5285521e1eSKumar Kartikeya Dwivedi 	__uint(map_flags, BPF_F_NO_PREALLOC);
5385521e1eSKumar Kartikeya Dwivedi } pcpu_hash_malloc_map SEC(".maps");
5485521e1eSKumar Kartikeya Dwivedi 
552cbc469aSKumar Kartikeya Dwivedi struct lru_hash_map {
562cbc469aSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_LRU_HASH);
572cbc469aSKumar Kartikeya Dwivedi 	__type(key, int);
582cbc469aSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
592cbc469aSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
602cbc469aSKumar Kartikeya Dwivedi } lru_hash_map SEC(".maps");
612cbc469aSKumar Kartikeya Dwivedi 
6285521e1eSKumar Kartikeya Dwivedi struct lru_pcpu_hash_map {
6385521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_LRU_PERCPU_HASH);
6485521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
6585521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
6685521e1eSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
6785521e1eSKumar Kartikeya Dwivedi } lru_pcpu_hash_map SEC(".maps");
6885521e1eSKumar Kartikeya Dwivedi 
6985521e1eSKumar Kartikeya Dwivedi struct cgrp_ls_map {
7085521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_CGRP_STORAGE);
7185521e1eSKumar Kartikeya Dwivedi 	__uint(map_flags, BPF_F_NO_PREALLOC);
7285521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
7385521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
7485521e1eSKumar Kartikeya Dwivedi } cgrp_ls_map SEC(".maps");
7585521e1eSKumar Kartikeya Dwivedi 
7685521e1eSKumar Kartikeya Dwivedi struct task_ls_map {
7785521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_TASK_STORAGE);
7885521e1eSKumar Kartikeya Dwivedi 	__uint(map_flags, BPF_F_NO_PREALLOC);
7985521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
8085521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
8185521e1eSKumar Kartikeya Dwivedi } task_ls_map SEC(".maps");
8285521e1eSKumar Kartikeya Dwivedi 
8385521e1eSKumar Kartikeya Dwivedi struct inode_ls_map {
8485521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_INODE_STORAGE);
8585521e1eSKumar Kartikeya Dwivedi 	__uint(map_flags, BPF_F_NO_PREALLOC);
8685521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
8785521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
8885521e1eSKumar Kartikeya Dwivedi } inode_ls_map SEC(".maps");
8985521e1eSKumar Kartikeya Dwivedi 
9085521e1eSKumar Kartikeya Dwivedi struct sk_ls_map {
9185521e1eSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_SK_STORAGE);
9285521e1eSKumar Kartikeya Dwivedi 	__uint(map_flags, BPF_F_NO_PREALLOC);
9385521e1eSKumar Kartikeya Dwivedi 	__type(key, int);
9485521e1eSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
9585521e1eSKumar Kartikeya Dwivedi } sk_ls_map SEC(".maps");
9685521e1eSKumar Kartikeya Dwivedi 
972cbc469aSKumar Kartikeya Dwivedi #define DEFINE_MAP_OF_MAP(map_type, inner_map_type, name)       \
982cbc469aSKumar Kartikeya Dwivedi 	struct {                                                \
992cbc469aSKumar Kartikeya Dwivedi 		__uint(type, map_type);                         \
1002cbc469aSKumar Kartikeya Dwivedi 		__uint(max_entries, 1);                         \
1012cbc469aSKumar Kartikeya Dwivedi 		__uint(key_size, sizeof(int));                  \
1022cbc469aSKumar Kartikeya Dwivedi 		__uint(value_size, sizeof(int));                \
1032cbc469aSKumar Kartikeya Dwivedi 		__array(values, struct inner_map_type);         \
1042cbc469aSKumar Kartikeya Dwivedi 	} name SEC(".maps") = {                                 \
1052cbc469aSKumar Kartikeya Dwivedi 		.values = { [0] = &inner_map_type },            \
1062cbc469aSKumar Kartikeya Dwivedi 	}
1072cbc469aSKumar Kartikeya Dwivedi 
1082cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_map, array_of_array_maps);
1092cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_map, array_of_hash_maps);
1102cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, hash_malloc_map, array_of_hash_malloc_maps);
1112cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_ARRAY_OF_MAPS, lru_hash_map, array_of_lru_hash_maps);
1122cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, array_map, hash_of_array_maps);
1132cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_map, hash_of_hash_maps);
1142cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, hash_malloc_map, hash_of_hash_malloc_maps);
1152cbc469aSKumar Kartikeya Dwivedi DEFINE_MAP_OF_MAP(BPF_MAP_TYPE_HASH_OF_MAPS, lru_hash_map, hash_of_lru_hash_maps);
1162cbc469aSKumar Kartikeya Dwivedi 
1172cbc469aSKumar Kartikeya Dwivedi extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym;
1182cbc469aSKumar Kartikeya Dwivedi extern struct prog_test_ref_kfunc *
1192cbc469aSKumar Kartikeya Dwivedi bpf_kfunc_call_test_kptr_get(struct prog_test_ref_kfunc **p, int a, int b) __ksym;
1202cbc469aSKumar Kartikeya Dwivedi extern void bpf_kfunc_call_test_release(struct prog_test_ref_kfunc *p) __ksym;
1212cbc469aSKumar Kartikeya Dwivedi 
12262d101d5SAlexei Starovoitov #define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val))
12362d101d5SAlexei Starovoitov 
1242cbc469aSKumar Kartikeya Dwivedi static void test_kptr_unref(struct map_value *v)
1252cbc469aSKumar Kartikeya Dwivedi {
1262cbc469aSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
1272cbc469aSKumar Kartikeya Dwivedi 
1282cbc469aSKumar Kartikeya Dwivedi 	p = v->unref_ptr;
1292cbc469aSKumar Kartikeya Dwivedi 	/* store untrusted_ptr_or_null_ */
13062d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1312cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1322cbc469aSKumar Kartikeya Dwivedi 		return;
1332cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100)
1342cbc469aSKumar Kartikeya Dwivedi 		return;
1352cbc469aSKumar Kartikeya Dwivedi 	/* store untrusted_ptr_ */
13662d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1372cbc469aSKumar Kartikeya Dwivedi 	/* store NULL */
13862d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, NULL);
1392cbc469aSKumar Kartikeya Dwivedi }
1402cbc469aSKumar Kartikeya Dwivedi 
1412cbc469aSKumar Kartikeya Dwivedi static void test_kptr_ref(struct map_value *v)
1422cbc469aSKumar Kartikeya Dwivedi {
1432cbc469aSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
1442cbc469aSKumar Kartikeya Dwivedi 
1452cbc469aSKumar Kartikeya Dwivedi 	p = v->ref_ptr;
1462cbc469aSKumar Kartikeya Dwivedi 	/* store ptr_or_null_ */
14762d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1482cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1492cbc469aSKumar Kartikeya Dwivedi 		return;
1502cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100)
1512cbc469aSKumar Kartikeya Dwivedi 		return;
1522cbc469aSKumar Kartikeya Dwivedi 	/* store NULL */
1532cbc469aSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, NULL);
1542cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1552cbc469aSKumar Kartikeya Dwivedi 		return;
1562cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100) {
1572cbc469aSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
1582cbc469aSKumar Kartikeya Dwivedi 		return;
1592cbc469aSKumar Kartikeya Dwivedi 	}
1602cbc469aSKumar Kartikeya Dwivedi 	/* store ptr_ */
16162d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1622cbc469aSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
1632cbc469aSKumar Kartikeya Dwivedi 
1642cbc469aSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&(unsigned long){0});
1652cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1662cbc469aSKumar Kartikeya Dwivedi 		return;
1672cbc469aSKumar Kartikeya Dwivedi 	/* store ptr_ */
1682cbc469aSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, p);
1692cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1702cbc469aSKumar Kartikeya Dwivedi 		return;
1712cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100) {
1722cbc469aSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
1732cbc469aSKumar Kartikeya Dwivedi 		return;
1742cbc469aSKumar Kartikeya Dwivedi 	}
1752cbc469aSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
1762cbc469aSKumar Kartikeya Dwivedi }
1772cbc469aSKumar Kartikeya Dwivedi 
1782cbc469aSKumar Kartikeya Dwivedi static void test_kptr_get(struct map_value *v)
1792cbc469aSKumar Kartikeya Dwivedi {
1802cbc469aSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
1812cbc469aSKumar Kartikeya Dwivedi 
1822cbc469aSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_kptr_get(&v->ref_ptr, 0, 0);
1832cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1842cbc469aSKumar Kartikeya Dwivedi 		return;
1852cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100) {
1862cbc469aSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
1872cbc469aSKumar Kartikeya Dwivedi 		return;
1882cbc469aSKumar Kartikeya Dwivedi 	}
1892cbc469aSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
1902cbc469aSKumar Kartikeya Dwivedi }
1912cbc469aSKumar Kartikeya Dwivedi 
1922cbc469aSKumar Kartikeya Dwivedi static void test_kptr(struct map_value *v)
1932cbc469aSKumar Kartikeya Dwivedi {
1942cbc469aSKumar Kartikeya Dwivedi 	test_kptr_unref(v);
1952cbc469aSKumar Kartikeya Dwivedi 	test_kptr_ref(v);
1962cbc469aSKumar Kartikeya Dwivedi 	test_kptr_get(v);
1972cbc469aSKumar Kartikeya Dwivedi }
1982cbc469aSKumar Kartikeya Dwivedi 
1992cbc469aSKumar Kartikeya Dwivedi SEC("tc")
2002cbc469aSKumar Kartikeya Dwivedi int test_map_kptr(struct __sk_buff *ctx)
2012cbc469aSKumar Kartikeya Dwivedi {
2022cbc469aSKumar Kartikeya Dwivedi 	struct map_value *v;
2030ef6740eSKumar Kartikeya Dwivedi 	int key = 0;
2042cbc469aSKumar Kartikeya Dwivedi 
2052cbc469aSKumar Kartikeya Dwivedi #define TEST(map)					\
2062cbc469aSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_elem(&map, &key);		\
2072cbc469aSKumar Kartikeya Dwivedi 	if (!v)						\
2082cbc469aSKumar Kartikeya Dwivedi 		return 0;				\
2092cbc469aSKumar Kartikeya Dwivedi 	test_kptr(v)
2102cbc469aSKumar Kartikeya Dwivedi 
2112cbc469aSKumar Kartikeya Dwivedi 	TEST(array_map);
2122cbc469aSKumar Kartikeya Dwivedi 	TEST(hash_map);
2132cbc469aSKumar Kartikeya Dwivedi 	TEST(hash_malloc_map);
2142cbc469aSKumar Kartikeya Dwivedi 	TEST(lru_hash_map);
2152cbc469aSKumar Kartikeya Dwivedi 
2162cbc469aSKumar Kartikeya Dwivedi #undef TEST
2172cbc469aSKumar Kartikeya Dwivedi 	return 0;
2182cbc469aSKumar Kartikeya Dwivedi }
2192cbc469aSKumar Kartikeya Dwivedi 
22085521e1eSKumar Kartikeya Dwivedi SEC("tp_btf/cgroup_mkdir")
22185521e1eSKumar Kartikeya Dwivedi int BPF_PROG(test_cgrp_map_kptr, struct cgroup *cgrp, const char *path)
22285521e1eSKumar Kartikeya Dwivedi {
22385521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
22485521e1eSKumar Kartikeya Dwivedi 
22585521e1eSKumar Kartikeya Dwivedi 	v = bpf_cgrp_storage_get(&cgrp_ls_map, cgrp, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
22685521e1eSKumar Kartikeya Dwivedi 	if (v)
22785521e1eSKumar Kartikeya Dwivedi 		test_kptr(v);
22885521e1eSKumar Kartikeya Dwivedi 	return 0;
22985521e1eSKumar Kartikeya Dwivedi }
23085521e1eSKumar Kartikeya Dwivedi 
23185521e1eSKumar Kartikeya Dwivedi SEC("lsm/inode_unlink")
23285521e1eSKumar Kartikeya Dwivedi int BPF_PROG(test_task_map_kptr, struct inode *inode, struct dentry *victim)
23385521e1eSKumar Kartikeya Dwivedi {
23485521e1eSKumar Kartikeya Dwivedi 	struct task_struct *task;
23585521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
23685521e1eSKumar Kartikeya Dwivedi 
23785521e1eSKumar Kartikeya Dwivedi 	task = bpf_get_current_task_btf();
23885521e1eSKumar Kartikeya Dwivedi 	if (!task)
23985521e1eSKumar Kartikeya Dwivedi 		return 0;
24085521e1eSKumar Kartikeya Dwivedi 	v = bpf_task_storage_get(&task_ls_map, task, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
24185521e1eSKumar Kartikeya Dwivedi 	if (v)
24285521e1eSKumar Kartikeya Dwivedi 		test_kptr(v);
24385521e1eSKumar Kartikeya Dwivedi 	return 0;
24485521e1eSKumar Kartikeya Dwivedi }
24585521e1eSKumar Kartikeya Dwivedi 
24685521e1eSKumar Kartikeya Dwivedi SEC("lsm/inode_unlink")
24785521e1eSKumar Kartikeya Dwivedi int BPF_PROG(test_inode_map_kptr, struct inode *inode, struct dentry *victim)
24885521e1eSKumar Kartikeya Dwivedi {
24985521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
25085521e1eSKumar Kartikeya Dwivedi 
25185521e1eSKumar Kartikeya Dwivedi 	v = bpf_inode_storage_get(&inode_ls_map, inode, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
25285521e1eSKumar Kartikeya Dwivedi 	if (v)
25385521e1eSKumar Kartikeya Dwivedi 		test_kptr(v);
25485521e1eSKumar Kartikeya Dwivedi 	return 0;
25585521e1eSKumar Kartikeya Dwivedi }
25685521e1eSKumar Kartikeya Dwivedi 
25785521e1eSKumar Kartikeya Dwivedi SEC("tc")
25885521e1eSKumar Kartikeya Dwivedi int test_sk_map_kptr(struct __sk_buff *ctx)
25985521e1eSKumar Kartikeya Dwivedi {
26085521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
26185521e1eSKumar Kartikeya Dwivedi 	struct bpf_sock *sk;
26285521e1eSKumar Kartikeya Dwivedi 
26385521e1eSKumar Kartikeya Dwivedi 	sk = ctx->sk;
26485521e1eSKumar Kartikeya Dwivedi 	if (!sk)
26585521e1eSKumar Kartikeya Dwivedi 		return 0;
26685521e1eSKumar Kartikeya Dwivedi 	v = bpf_sk_storage_get(&sk_ls_map, sk, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
26785521e1eSKumar Kartikeya Dwivedi 	if (v)
26885521e1eSKumar Kartikeya Dwivedi 		test_kptr(v);
26985521e1eSKumar Kartikeya Dwivedi 	return 0;
27085521e1eSKumar Kartikeya Dwivedi }
27185521e1eSKumar Kartikeya Dwivedi 
2722cbc469aSKumar Kartikeya Dwivedi SEC("tc")
2732cbc469aSKumar Kartikeya Dwivedi int test_map_in_map_kptr(struct __sk_buff *ctx)
2742cbc469aSKumar Kartikeya Dwivedi {
2752cbc469aSKumar Kartikeya Dwivedi 	struct map_value *v;
2760ef6740eSKumar Kartikeya Dwivedi 	int key = 0;
2772cbc469aSKumar Kartikeya Dwivedi 	void *map;
2782cbc469aSKumar Kartikeya Dwivedi 
2792cbc469aSKumar Kartikeya Dwivedi #define TEST(map_in_map)                                \
2802cbc469aSKumar Kartikeya Dwivedi 	map = bpf_map_lookup_elem(&map_in_map, &key);   \
2812cbc469aSKumar Kartikeya Dwivedi 	if (!map)                                       \
2822cbc469aSKumar Kartikeya Dwivedi 		return 0;                               \
2832cbc469aSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_elem(map, &key);		\
2842cbc469aSKumar Kartikeya Dwivedi 	if (!v)						\
2852cbc469aSKumar Kartikeya Dwivedi 		return 0;				\
2862cbc469aSKumar Kartikeya Dwivedi 	test_kptr(v)
2872cbc469aSKumar Kartikeya Dwivedi 
2882cbc469aSKumar Kartikeya Dwivedi 	TEST(array_of_array_maps);
2892cbc469aSKumar Kartikeya Dwivedi 	TEST(array_of_hash_maps);
2902cbc469aSKumar Kartikeya Dwivedi 	TEST(array_of_hash_malloc_maps);
2912cbc469aSKumar Kartikeya Dwivedi 	TEST(array_of_lru_hash_maps);
2922cbc469aSKumar Kartikeya Dwivedi 	TEST(hash_of_array_maps);
2932cbc469aSKumar Kartikeya Dwivedi 	TEST(hash_of_hash_maps);
2942cbc469aSKumar Kartikeya Dwivedi 	TEST(hash_of_hash_malloc_maps);
2952cbc469aSKumar Kartikeya Dwivedi 	TEST(hash_of_lru_hash_maps);
2962cbc469aSKumar Kartikeya Dwivedi 
2972cbc469aSKumar Kartikeya Dwivedi #undef TEST
2982cbc469aSKumar Kartikeya Dwivedi 	return 0;
2992cbc469aSKumar Kartikeya Dwivedi }
3002cbc469aSKumar Kartikeya Dwivedi 
30185521e1eSKumar Kartikeya Dwivedi int ref = 1;
30285521e1eSKumar Kartikeya Dwivedi 
30385521e1eSKumar Kartikeya Dwivedi static __always_inline
30485521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref_pre(struct map_value *v)
3050ef6740eSKumar Kartikeya Dwivedi {
3060ef6740eSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p, *p_st;
3070ef6740eSKumar Kartikeya Dwivedi 	unsigned long arg = 0;
30885521e1eSKumar Kartikeya Dwivedi 	int ret;
3090ef6740eSKumar Kartikeya Dwivedi 
3100ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&arg);
3110ef6740eSKumar Kartikeya Dwivedi 	if (!p)
3120ef6740eSKumar Kartikeya Dwivedi 		return 1;
31385521e1eSKumar Kartikeya Dwivedi 	ref++;
3140ef6740eSKumar Kartikeya Dwivedi 
3150ef6740eSKumar Kartikeya Dwivedi 	p_st = p->next;
31685521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref) {
3170ef6740eSKumar Kartikeya Dwivedi 		ret = 2;
3180ef6740eSKumar Kartikeya Dwivedi 		goto end;
3190ef6740eSKumar Kartikeya Dwivedi 	}
3200ef6740eSKumar Kartikeya Dwivedi 
32185521e1eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, p);
32285521e1eSKumar Kartikeya Dwivedi 	if (p) {
3230ef6740eSKumar Kartikeya Dwivedi 		ret = 3;
3240ef6740eSKumar Kartikeya Dwivedi 		goto end;
3250ef6740eSKumar Kartikeya Dwivedi 	}
32685521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
32785521e1eSKumar Kartikeya Dwivedi 		return 4;
3280ef6740eSKumar Kartikeya Dwivedi 
3290ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_kptr_get(&v->ref_ptr, 0, 0);
3300ef6740eSKumar Kartikeya Dwivedi 	if (!p)
33185521e1eSKumar Kartikeya Dwivedi 		return 5;
33285521e1eSKumar Kartikeya Dwivedi 	ref++;
33385521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref) {
33485521e1eSKumar Kartikeya Dwivedi 		ret = 6;
3350ef6740eSKumar Kartikeya Dwivedi 		goto end;
3360ef6740eSKumar Kartikeya Dwivedi 	}
3370ef6740eSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
33885521e1eSKumar Kartikeya Dwivedi 	ref--;
33985521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
34085521e1eSKumar Kartikeya Dwivedi 		return 7;
3410ef6740eSKumar Kartikeya Dwivedi 
3420ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, NULL);
3430ef6740eSKumar Kartikeya Dwivedi 	if (!p)
34485521e1eSKumar Kartikeya Dwivedi 		return 8;
3450ef6740eSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
34685521e1eSKumar Kartikeya Dwivedi 	ref--;
34785521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
34885521e1eSKumar Kartikeya Dwivedi 		return 9;
3490ef6740eSKumar Kartikeya Dwivedi 
3500ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&arg);
3510ef6740eSKumar Kartikeya Dwivedi 	if (!p)
35285521e1eSKumar Kartikeya Dwivedi 		return 10;
35385521e1eSKumar Kartikeya Dwivedi 	ref++;
3540ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, p);
3550ef6740eSKumar Kartikeya Dwivedi 	if (p) {
35685521e1eSKumar Kartikeya Dwivedi 		ret = 11;
3570ef6740eSKumar Kartikeya Dwivedi 		goto end;
3580ef6740eSKumar Kartikeya Dwivedi 	}
35985521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
36085521e1eSKumar Kartikeya Dwivedi 		return 12;
3610ef6740eSKumar Kartikeya Dwivedi 	/* Leave in map */
3620ef6740eSKumar Kartikeya Dwivedi 
3630ef6740eSKumar Kartikeya Dwivedi 	return 0;
3640ef6740eSKumar Kartikeya Dwivedi end:
36585521e1eSKumar Kartikeya Dwivedi 	ref--;
3660ef6740eSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
3670ef6740eSKumar Kartikeya Dwivedi 	return ret;
3680ef6740eSKumar Kartikeya Dwivedi }
3690ef6740eSKumar Kartikeya Dwivedi 
37085521e1eSKumar Kartikeya Dwivedi static __always_inline
37185521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref_post(struct map_value *v)
3720ef6740eSKumar Kartikeya Dwivedi {
3730ef6740eSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p, *p_st;
3740ef6740eSKumar Kartikeya Dwivedi 
3750ef6740eSKumar Kartikeya Dwivedi 	p_st = v->ref_ptr;
37685521e1eSKumar Kartikeya Dwivedi 	if (!p_st || p_st->cnt.refs.counter != ref)
37785521e1eSKumar Kartikeya Dwivedi 		return 1;
3780ef6740eSKumar Kartikeya Dwivedi 
3790ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, NULL);
3800ef6740eSKumar Kartikeya Dwivedi 	if (!p)
38185521e1eSKumar Kartikeya Dwivedi 		return 2;
38285521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref) {
3830ef6740eSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
38485521e1eSKumar Kartikeya Dwivedi 		return 3;
3850ef6740eSKumar Kartikeya Dwivedi 	}
3860ef6740eSKumar Kartikeya Dwivedi 
3870ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, p);
3880ef6740eSKumar Kartikeya Dwivedi 	if (p) {
3890ef6740eSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
39085521e1eSKumar Kartikeya Dwivedi 		return 4;
3910ef6740eSKumar Kartikeya Dwivedi 	}
39285521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
39385521e1eSKumar Kartikeya Dwivedi 		return 5;
3940ef6740eSKumar Kartikeya Dwivedi 
3950ef6740eSKumar Kartikeya Dwivedi 	return 0;
3960ef6740eSKumar Kartikeya Dwivedi }
3970ef6740eSKumar Kartikeya Dwivedi 
39885521e1eSKumar Kartikeya Dwivedi #define TEST(map)                            \
39985521e1eSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_elem(&map, &key); \
40085521e1eSKumar Kartikeya Dwivedi 	if (!v)                              \
40185521e1eSKumar Kartikeya Dwivedi 		return -1;                   \
40285521e1eSKumar Kartikeya Dwivedi 	ret = test_map_kptr_ref_pre(v);      \
40385521e1eSKumar Kartikeya Dwivedi 	if (ret)                             \
40485521e1eSKumar Kartikeya Dwivedi 		return ret;
40585521e1eSKumar Kartikeya Dwivedi 
40685521e1eSKumar Kartikeya Dwivedi #define TEST_PCPU(map)                                 \
40785521e1eSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_percpu_elem(&map, &key, 0); \
40885521e1eSKumar Kartikeya Dwivedi 	if (!v)                                        \
40985521e1eSKumar Kartikeya Dwivedi 		return -1;                             \
41085521e1eSKumar Kartikeya Dwivedi 	ret = test_map_kptr_ref_pre(v);                \
41185521e1eSKumar Kartikeya Dwivedi 	if (ret)                                       \
41285521e1eSKumar Kartikeya Dwivedi 		return ret;
41385521e1eSKumar Kartikeya Dwivedi 
41485521e1eSKumar Kartikeya Dwivedi SEC("tc")
41585521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref1(struct __sk_buff *ctx)
41685521e1eSKumar Kartikeya Dwivedi {
41785521e1eSKumar Kartikeya Dwivedi 	struct map_value *v, val = {};
41885521e1eSKumar Kartikeya Dwivedi 	int key = 0, ret;
41985521e1eSKumar Kartikeya Dwivedi 
42085521e1eSKumar Kartikeya Dwivedi 	bpf_map_update_elem(&hash_map, &key, &val, 0);
42185521e1eSKumar Kartikeya Dwivedi 	bpf_map_update_elem(&hash_malloc_map, &key, &val, 0);
42285521e1eSKumar Kartikeya Dwivedi 	bpf_map_update_elem(&lru_hash_map, &key, &val, 0);
42385521e1eSKumar Kartikeya Dwivedi 
42485521e1eSKumar Kartikeya Dwivedi 	bpf_map_update_elem(&pcpu_hash_map, &key, &val, 0);
42585521e1eSKumar Kartikeya Dwivedi 	bpf_map_update_elem(&pcpu_hash_malloc_map, &key, &val, 0);
42685521e1eSKumar Kartikeya Dwivedi 	bpf_map_update_elem(&lru_pcpu_hash_map, &key, &val, 0);
42785521e1eSKumar Kartikeya Dwivedi 
42885521e1eSKumar Kartikeya Dwivedi 	TEST(array_map);
42985521e1eSKumar Kartikeya Dwivedi 	TEST(hash_map);
43085521e1eSKumar Kartikeya Dwivedi 	TEST(hash_malloc_map);
43185521e1eSKumar Kartikeya Dwivedi 	TEST(lru_hash_map);
43285521e1eSKumar Kartikeya Dwivedi 
43385521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(pcpu_array_map);
43485521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(pcpu_hash_map);
43585521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(pcpu_hash_malloc_map);
43685521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(lru_pcpu_hash_map);
43785521e1eSKumar Kartikeya Dwivedi 
43885521e1eSKumar Kartikeya Dwivedi 	return 0;
43985521e1eSKumar Kartikeya Dwivedi }
44085521e1eSKumar Kartikeya Dwivedi 
44185521e1eSKumar Kartikeya Dwivedi #undef TEST
44285521e1eSKumar Kartikeya Dwivedi #undef TEST_PCPU
44385521e1eSKumar Kartikeya Dwivedi 
44485521e1eSKumar Kartikeya Dwivedi #define TEST(map)                            \
44585521e1eSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_elem(&map, &key); \
44685521e1eSKumar Kartikeya Dwivedi 	if (!v)                              \
44785521e1eSKumar Kartikeya Dwivedi 		return -1;                   \
44885521e1eSKumar Kartikeya Dwivedi 	ret = test_map_kptr_ref_post(v);     \
44985521e1eSKumar Kartikeya Dwivedi 	if (ret)                             \
45085521e1eSKumar Kartikeya Dwivedi 		return ret;
45185521e1eSKumar Kartikeya Dwivedi 
45285521e1eSKumar Kartikeya Dwivedi #define TEST_PCPU(map)                                 \
45385521e1eSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_percpu_elem(&map, &key, 0); \
45485521e1eSKumar Kartikeya Dwivedi 	if (!v)                                        \
45585521e1eSKumar Kartikeya Dwivedi 		return -1;                             \
45685521e1eSKumar Kartikeya Dwivedi 	ret = test_map_kptr_ref_post(v);               \
45785521e1eSKumar Kartikeya Dwivedi 	if (ret)                                       \
45885521e1eSKumar Kartikeya Dwivedi 		return ret;
45985521e1eSKumar Kartikeya Dwivedi 
46085521e1eSKumar Kartikeya Dwivedi SEC("tc")
46185521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref2(struct __sk_buff *ctx)
46285521e1eSKumar Kartikeya Dwivedi {
46385521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
46485521e1eSKumar Kartikeya Dwivedi 	int key = 0, ret;
46585521e1eSKumar Kartikeya Dwivedi 
46685521e1eSKumar Kartikeya Dwivedi 	TEST(array_map);
46785521e1eSKumar Kartikeya Dwivedi 	TEST(hash_map);
46885521e1eSKumar Kartikeya Dwivedi 	TEST(hash_malloc_map);
46985521e1eSKumar Kartikeya Dwivedi 	TEST(lru_hash_map);
47085521e1eSKumar Kartikeya Dwivedi 
47185521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(pcpu_array_map);
47285521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(pcpu_hash_map);
47385521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(pcpu_hash_malloc_map);
47485521e1eSKumar Kartikeya Dwivedi 	TEST_PCPU(lru_pcpu_hash_map);
47585521e1eSKumar Kartikeya Dwivedi 
47685521e1eSKumar Kartikeya Dwivedi 	return 0;
47785521e1eSKumar Kartikeya Dwivedi }
47885521e1eSKumar Kartikeya Dwivedi 
47985521e1eSKumar Kartikeya Dwivedi #undef TEST
48085521e1eSKumar Kartikeya Dwivedi #undef TEST_PCPU
48185521e1eSKumar Kartikeya Dwivedi 
48285521e1eSKumar Kartikeya Dwivedi SEC("tc")
48385521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref3(struct __sk_buff *ctx)
48485521e1eSKumar Kartikeya Dwivedi {
48585521e1eSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
48685521e1eSKumar Kartikeya Dwivedi 	unsigned long sp = 0;
48785521e1eSKumar Kartikeya Dwivedi 
48885521e1eSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&sp);
48985521e1eSKumar Kartikeya Dwivedi 	if (!p)
49085521e1eSKumar Kartikeya Dwivedi 		return 1;
49185521e1eSKumar Kartikeya Dwivedi 	ref++;
49285521e1eSKumar Kartikeya Dwivedi 	if (p->cnt.refs.counter != ref) {
49385521e1eSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
49485521e1eSKumar Kartikeya Dwivedi 		return 2;
49585521e1eSKumar Kartikeya Dwivedi 	}
49685521e1eSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
49785521e1eSKumar Kartikeya Dwivedi 	ref--;
49885521e1eSKumar Kartikeya Dwivedi 	return 0;
49985521e1eSKumar Kartikeya Dwivedi }
50085521e1eSKumar Kartikeya Dwivedi 
50185521e1eSKumar Kartikeya Dwivedi SEC("syscall")
50285521e1eSKumar Kartikeya Dwivedi int test_ls_map_kptr_ref1(void *ctx)
50385521e1eSKumar Kartikeya Dwivedi {
50485521e1eSKumar Kartikeya Dwivedi 	struct task_struct *current;
50585521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
50685521e1eSKumar Kartikeya Dwivedi 	int ret;
50785521e1eSKumar Kartikeya Dwivedi 
50885521e1eSKumar Kartikeya Dwivedi 	current = bpf_get_current_task_btf();
50985521e1eSKumar Kartikeya Dwivedi 	if (!current)
51085521e1eSKumar Kartikeya Dwivedi 		return 100;
51185521e1eSKumar Kartikeya Dwivedi 	v = bpf_task_storage_get(&task_ls_map, current, NULL, 0);
51285521e1eSKumar Kartikeya Dwivedi 	if (v)
51385521e1eSKumar Kartikeya Dwivedi 		return 150;
51485521e1eSKumar Kartikeya Dwivedi 	v = bpf_task_storage_get(&task_ls_map, current, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
51585521e1eSKumar Kartikeya Dwivedi 	if (!v)
51685521e1eSKumar Kartikeya Dwivedi 		return 200;
51785521e1eSKumar Kartikeya Dwivedi 	return test_map_kptr_ref_pre(v);
51885521e1eSKumar Kartikeya Dwivedi }
51985521e1eSKumar Kartikeya Dwivedi 
52085521e1eSKumar Kartikeya Dwivedi SEC("syscall")
52185521e1eSKumar Kartikeya Dwivedi int test_ls_map_kptr_ref2(void *ctx)
52285521e1eSKumar Kartikeya Dwivedi {
52385521e1eSKumar Kartikeya Dwivedi 	struct task_struct *current;
52485521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
52585521e1eSKumar Kartikeya Dwivedi 	int ret;
52685521e1eSKumar Kartikeya Dwivedi 
52785521e1eSKumar Kartikeya Dwivedi 	current = bpf_get_current_task_btf();
52885521e1eSKumar Kartikeya Dwivedi 	if (!current)
52985521e1eSKumar Kartikeya Dwivedi 		return 100;
53085521e1eSKumar Kartikeya Dwivedi 	v = bpf_task_storage_get(&task_ls_map, current, NULL, 0);
53185521e1eSKumar Kartikeya Dwivedi 	if (!v)
53285521e1eSKumar Kartikeya Dwivedi 		return 200;
53385521e1eSKumar Kartikeya Dwivedi 	return test_map_kptr_ref_post(v);
53485521e1eSKumar Kartikeya Dwivedi }
53585521e1eSKumar Kartikeya Dwivedi 
53685521e1eSKumar Kartikeya Dwivedi SEC("syscall")
53785521e1eSKumar Kartikeya Dwivedi int test_ls_map_kptr_ref_del(void *ctx)
53885521e1eSKumar Kartikeya Dwivedi {
53985521e1eSKumar Kartikeya Dwivedi 	struct task_struct *current;
54085521e1eSKumar Kartikeya Dwivedi 	struct map_value *v;
54185521e1eSKumar Kartikeya Dwivedi 	int ret;
54285521e1eSKumar Kartikeya Dwivedi 
54385521e1eSKumar Kartikeya Dwivedi 	current = bpf_get_current_task_btf();
54485521e1eSKumar Kartikeya Dwivedi 	if (!current)
54585521e1eSKumar Kartikeya Dwivedi 		return 100;
54685521e1eSKumar Kartikeya Dwivedi 	v = bpf_task_storage_get(&task_ls_map, current, NULL, 0);
54785521e1eSKumar Kartikeya Dwivedi 	if (!v)
54885521e1eSKumar Kartikeya Dwivedi 		return 200;
54985521e1eSKumar Kartikeya Dwivedi 	if (!v->ref_ptr)
55085521e1eSKumar Kartikeya Dwivedi 		return 300;
55185521e1eSKumar Kartikeya Dwivedi 	return bpf_task_storage_delete(&task_ls_map, current);
55285521e1eSKumar Kartikeya Dwivedi }
55385521e1eSKumar Kartikeya Dwivedi 
5542cbc469aSKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
555