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>
5*8e9af821SJiri Olsa #include "../bpf_testmod/bpf_testmod_kfunc.h"
62cbc469aSKumar Kartikeya Dwivedi 
72cbc469aSKumar Kartikeya Dwivedi struct map_value {
803b77e17SAlexei Starovoitov 	struct prog_test_ref_kfunc __kptr_untrusted *unref_ptr;
903b77e17SAlexei Starovoitov 	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");
182cbc469aSKumar 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");
2585521e1eSKumar 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");
322cbc469aSKumar 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");
3985521e1eSKumar 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");
472cbc469aSKumar 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");
5585521e1eSKumar 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");
622cbc469aSKumar 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");
9785521e1eSKumar 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 
11862d101d5SAlexei Starovoitov #define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val))
11962d101d5SAlexei Starovoitov 
test_kptr_unref(struct map_value * v)1202cbc469aSKumar Kartikeya Dwivedi static void test_kptr_unref(struct map_value *v)
1212cbc469aSKumar Kartikeya Dwivedi {
1222cbc469aSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
1232cbc469aSKumar Kartikeya Dwivedi 
1242cbc469aSKumar Kartikeya Dwivedi 	p = v->unref_ptr;
1252cbc469aSKumar Kartikeya Dwivedi 	/* store untrusted_ptr_or_null_ */
12662d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1272cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1282cbc469aSKumar Kartikeya Dwivedi 		return;
1292cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100)
1302cbc469aSKumar Kartikeya Dwivedi 		return;
1312cbc469aSKumar Kartikeya Dwivedi 	/* store untrusted_ptr_ */
13262d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1332cbc469aSKumar Kartikeya Dwivedi 	/* store NULL */
13462d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, NULL);
1352cbc469aSKumar Kartikeya Dwivedi }
1362cbc469aSKumar Kartikeya Dwivedi 
test_kptr_ref(struct map_value * v)1372cbc469aSKumar Kartikeya Dwivedi 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_ */
14362d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1442cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1452cbc469aSKumar Kartikeya Dwivedi 		return;
146838bd4acSAlexei Starovoitov 	/*
147838bd4acSAlexei Starovoitov 	 * p is rcu_ptr_prog_test_ref_kfunc,
148838bd4acSAlexei Starovoitov 	 * 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);
1522cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100)
1532cbc469aSKumar Kartikeya Dwivedi 		return;
1542cbc469aSKumar Kartikeya Dwivedi 	/* store NULL */
1552cbc469aSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, NULL);
1562cbc469aSKumar Kartikeya Dwivedi 	if (!p)
1572cbc469aSKumar Kartikeya Dwivedi 		return;
158838bd4acSAlexei Starovoitov 	/*
159838bd4acSAlexei Starovoitov 	 * p is trusted_ptr_prog_test_ref_kfunc.
160838bd4acSAlexei Starovoitov 	 * p can be passed to kfunc that requires KF_RCU.
161838bd4acSAlexei Starovoitov 	 */
162838bd4acSAlexei Starovoitov 	bpf_kfunc_call_test_ref(p);
1632cbc469aSKumar Kartikeya Dwivedi 	if (p->a + p->b > 100) {
1642cbc469aSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
1652cbc469aSKumar Kartikeya Dwivedi 		return;
1662cbc469aSKumar Kartikeya Dwivedi 	}
1672cbc469aSKumar Kartikeya Dwivedi 	/* store ptr_ */
16862d101d5SAlexei Starovoitov 	WRITE_ONCE(v->unref_ptr, p);
1692cbc469aSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
1702cbc469aSKumar Kartikeya Dwivedi 
1712cbc469aSKumar Kartikeya Dwivedi 	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;
1950ef6740eSKumar Kartikeya Dwivedi 	int key = 0;
1962cbc469aSKumar Kartikeya Dwivedi 
1972cbc469aSKumar Kartikeya Dwivedi #define TEST(map)					\
1982cbc469aSKumar 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 
21285521e1eSKumar Kartikeya Dwivedi SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_map_kptr,struct cgroup * cgrp,const char * path)21385521e1eSKumar Kartikeya Dwivedi int BPF_PROG(test_cgrp_map_kptr, struct cgroup *cgrp, const char *path)
21485521e1eSKumar 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 
2642cbc469aSKumar Kartikeya Dwivedi SEC("tc")
test_map_in_map_kptr(struct __sk_buff * ctx)2652cbc469aSKumar Kartikeya Dwivedi int test_map_in_map_kptr(struct __sk_buff *ctx)
2662cbc469aSKumar Kartikeya Dwivedi {
2672cbc469aSKumar Kartikeya Dwivedi 	struct map_value *v;
2680ef6740eSKumar Kartikeya Dwivedi 	int key = 0;
2692cbc469aSKumar Kartikeya Dwivedi 	void *map;
2702cbc469aSKumar Kartikeya Dwivedi 
2712cbc469aSKumar 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 
29385521e1eSKumar Kartikeya Dwivedi int ref = 1;
29485521e1eSKumar Kartikeya Dwivedi 
29585521e1eSKumar 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)
2970ef6740eSKumar Kartikeya Dwivedi {
2980ef6740eSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p, *p_st;
2990ef6740eSKumar Kartikeya Dwivedi 	unsigned long arg = 0;
30085521e1eSKumar Kartikeya Dwivedi 	int ret;
3010ef6740eSKumar Kartikeya Dwivedi 
3020ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&arg);
3030ef6740eSKumar Kartikeya Dwivedi 	if (!p)
3040ef6740eSKumar Kartikeya Dwivedi 		return 1;
30585521e1eSKumar 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;
3110ef6740eSKumar Kartikeya Dwivedi 	}
3120ef6740eSKumar Kartikeya Dwivedi 
31385521e1eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, p);
31485521e1eSKumar Kartikeya Dwivedi 	if (p) {
3150ef6740eSKumar Kartikeya Dwivedi 		ret = 3;
3160ef6740eSKumar Kartikeya Dwivedi 		goto end;
3170ef6740eSKumar Kartikeya Dwivedi 	}
31885521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
31985521e1eSKumar Kartikeya Dwivedi 		return 4;
3200ef6740eSKumar Kartikeya Dwivedi 
3210ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, NULL);
3220ef6740eSKumar Kartikeya Dwivedi 	if (!p)
32309b501d9SDavid Vernet 		return 5;
3240ef6740eSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
32585521e1eSKumar Kartikeya Dwivedi 	ref--;
32685521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
32709b501d9SDavid Vernet 		return 6;
3280ef6740eSKumar Kartikeya Dwivedi 
3290ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&arg);
3300ef6740eSKumar Kartikeya Dwivedi 	if (!p)
33109b501d9SDavid Vernet 		return 7;
33285521e1eSKumar Kartikeya Dwivedi 	ref++;
3330ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, p);
3340ef6740eSKumar Kartikeya Dwivedi 	if (p) {
33509b501d9SDavid Vernet 		ret = 8;
3360ef6740eSKumar Kartikeya Dwivedi 		goto end;
3370ef6740eSKumar Kartikeya Dwivedi 	}
33885521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
33909b501d9SDavid Vernet 		return 9;
3400ef6740eSKumar Kartikeya Dwivedi 	/* Leave in map */
3410ef6740eSKumar Kartikeya Dwivedi 
3420ef6740eSKumar Kartikeya Dwivedi 	return 0;
3430ef6740eSKumar Kartikeya Dwivedi end:
34485521e1eSKumar Kartikeya Dwivedi 	ref--;
3450ef6740eSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
3460ef6740eSKumar Kartikeya Dwivedi 	return ret;
3470ef6740eSKumar Kartikeya Dwivedi }
3480ef6740eSKumar Kartikeya Dwivedi 
34985521e1eSKumar Kartikeya Dwivedi static __always_inline
test_map_kptr_ref_post(struct map_value * v)35085521e1eSKumar Kartikeya Dwivedi int test_map_kptr_ref_post(struct map_value *v)
3510ef6740eSKumar Kartikeya Dwivedi {
3520ef6740eSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p, *p_st;
3530ef6740eSKumar Kartikeya Dwivedi 
3540ef6740eSKumar Kartikeya Dwivedi 	p_st = v->ref_ptr;
35585521e1eSKumar Kartikeya Dwivedi 	if (!p_st || p_st->cnt.refs.counter != ref)
35685521e1eSKumar Kartikeya Dwivedi 		return 1;
3570ef6740eSKumar Kartikeya Dwivedi 
3580ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, NULL);
3590ef6740eSKumar Kartikeya Dwivedi 	if (!p)
36085521e1eSKumar Kartikeya Dwivedi 		return 2;
36185521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref) {
3620ef6740eSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
36385521e1eSKumar Kartikeya Dwivedi 		return 3;
3640ef6740eSKumar Kartikeya Dwivedi 	}
3650ef6740eSKumar Kartikeya Dwivedi 
3660ef6740eSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ref_ptr, p);
3670ef6740eSKumar Kartikeya Dwivedi 	if (p) {
3680ef6740eSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
36985521e1eSKumar Kartikeya Dwivedi 		return 4;
3700ef6740eSKumar Kartikeya Dwivedi 	}
37185521e1eSKumar Kartikeya Dwivedi 	if (p_st->cnt.refs.counter != ref)
37285521e1eSKumar Kartikeya Dwivedi 		return 5;
3730ef6740eSKumar Kartikeya Dwivedi 
3740ef6740eSKumar Kartikeya Dwivedi 	return 0;
3750ef6740eSKumar Kartikeya Dwivedi }
3760ef6740eSKumar Kartikeya Dwivedi 
37785521e1eSKumar Kartikeya Dwivedi #define TEST(map)                            \
37885521e1eSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_elem(&map, &key); \
37985521e1eSKumar 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 
5302cbc469aSKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
531