135f14dbdSKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0
235f14dbdSKumar Kartikeya Dwivedi #include <vmlinux.h>
335f14dbdSKumar Kartikeya Dwivedi #include <bpf/bpf_tracing.h>
435f14dbdSKumar Kartikeya Dwivedi #include <bpf/bpf_helpers.h>
58e9af821SJiri Olsa #include "../bpf_testmod/bpf_testmod_kfunc.h"
635f14dbdSKumar Kartikeya Dwivedi 
735f14dbdSKumar Kartikeya Dwivedi struct map_value {
803b77e17SAlexei Starovoitov 	struct prog_test_ref_kfunc __kptr *ptr;
935f14dbdSKumar Kartikeya Dwivedi };
1035f14dbdSKumar Kartikeya Dwivedi 
1135f14dbdSKumar Kartikeya Dwivedi struct {
1235f14dbdSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_ARRAY);
1335f14dbdSKumar Kartikeya Dwivedi 	__type(key, int);
1435f14dbdSKumar Kartikeya Dwivedi 	__type(value, struct map_value);
1535f14dbdSKumar Kartikeya Dwivedi 	__uint(max_entries, 16);
1635f14dbdSKumar Kartikeya Dwivedi } array_map SEC(".maps");
1735f14dbdSKumar Kartikeya Dwivedi 
cb1(void * map,void * key,void * value,void * ctx)1835f14dbdSKumar Kartikeya Dwivedi static __noinline int cb1(void *map, void *key, void *value, void *ctx)
1935f14dbdSKumar Kartikeya Dwivedi {
2035f14dbdSKumar Kartikeya Dwivedi 	void *p = *(void **)ctx;
2135f14dbdSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
2235f14dbdSKumar Kartikeya Dwivedi 	/* Without the fix this would cause underflow */
2335f14dbdSKumar Kartikeya Dwivedi 	return 0;
2435f14dbdSKumar Kartikeya Dwivedi }
2535f14dbdSKumar Kartikeya Dwivedi 
2635f14dbdSKumar Kartikeya Dwivedi SEC("?tc")
underflow_prog(void * ctx)2735f14dbdSKumar Kartikeya Dwivedi int underflow_prog(void *ctx)
2835f14dbdSKumar Kartikeya Dwivedi {
2935f14dbdSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
3035f14dbdSKumar Kartikeya Dwivedi 	unsigned long sl = 0;
3135f14dbdSKumar Kartikeya Dwivedi 
3235f14dbdSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&sl);
3335f14dbdSKumar Kartikeya Dwivedi 	if (!p)
3435f14dbdSKumar Kartikeya Dwivedi 		return 0;
3535f14dbdSKumar Kartikeya Dwivedi 	bpf_for_each_map_elem(&array_map, cb1, &p, 0);
36*b43550d7SEduard Zingerman 	bpf_kfunc_call_test_release(p);
3735f14dbdSKumar Kartikeya Dwivedi 	return 0;
3835f14dbdSKumar Kartikeya Dwivedi }
3935f14dbdSKumar Kartikeya Dwivedi 
cb2(void * map,void * key,void * value,void * ctx)4035f14dbdSKumar Kartikeya Dwivedi static __always_inline int cb2(void *map, void *key, void *value, void *ctx)
4135f14dbdSKumar Kartikeya Dwivedi {
4235f14dbdSKumar Kartikeya Dwivedi 	unsigned long sl = 0;
4335f14dbdSKumar Kartikeya Dwivedi 
4435f14dbdSKumar Kartikeya Dwivedi 	*(void **)ctx = bpf_kfunc_call_test_acquire(&sl);
4535f14dbdSKumar Kartikeya Dwivedi 	/* Without the fix this would leak memory */
4635f14dbdSKumar Kartikeya Dwivedi 	return 0;
4735f14dbdSKumar Kartikeya Dwivedi }
4835f14dbdSKumar Kartikeya Dwivedi 
4935f14dbdSKumar Kartikeya Dwivedi SEC("?tc")
leak_prog(void * ctx)5035f14dbdSKumar Kartikeya Dwivedi int leak_prog(void *ctx)
5135f14dbdSKumar Kartikeya Dwivedi {
5235f14dbdSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
5335f14dbdSKumar Kartikeya Dwivedi 	struct map_value *v;
5435f14dbdSKumar Kartikeya Dwivedi 
5535f14dbdSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_elem(&array_map, &(int){0});
5635f14dbdSKumar Kartikeya Dwivedi 	if (!v)
5735f14dbdSKumar Kartikeya Dwivedi 		return 0;
5835f14dbdSKumar Kartikeya Dwivedi 
5935f14dbdSKumar Kartikeya Dwivedi 	p = NULL;
6035f14dbdSKumar Kartikeya Dwivedi 	bpf_for_each_map_elem(&array_map, cb2, &p, 0);
6135f14dbdSKumar Kartikeya Dwivedi 	p = bpf_kptr_xchg(&v->ptr, p);
6235f14dbdSKumar Kartikeya Dwivedi 	if (p)
6335f14dbdSKumar Kartikeya Dwivedi 		bpf_kfunc_call_test_release(p);
6435f14dbdSKumar Kartikeya Dwivedi 	return 0;
6535f14dbdSKumar Kartikeya Dwivedi }
6635f14dbdSKumar Kartikeya Dwivedi 
cb(void * map,void * key,void * value,void * ctx)6735f14dbdSKumar Kartikeya Dwivedi static __always_inline int cb(void *map, void *key, void *value, void *ctx)
6835f14dbdSKumar Kartikeya Dwivedi {
6935f14dbdSKumar Kartikeya Dwivedi 	return 0;
7035f14dbdSKumar Kartikeya Dwivedi }
7135f14dbdSKumar Kartikeya Dwivedi 
cb3(void * map,void * key,void * value,void * ctx)7235f14dbdSKumar Kartikeya Dwivedi static __always_inline int cb3(void *map, void *key, void *value, void *ctx)
7335f14dbdSKumar Kartikeya Dwivedi {
7435f14dbdSKumar Kartikeya Dwivedi 	unsigned long sl = 0;
7535f14dbdSKumar Kartikeya Dwivedi 	void *p;
7635f14dbdSKumar Kartikeya Dwivedi 
7735f14dbdSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_acquire(&sl);
7835f14dbdSKumar Kartikeya Dwivedi 	bpf_for_each_map_elem(&array_map, cb, &p, 0);
7935f14dbdSKumar Kartikeya Dwivedi 	/* It should only complain here, not in cb. This is why we need
8035f14dbdSKumar Kartikeya Dwivedi 	 * callback_ref to be set to frameno.
8135f14dbdSKumar Kartikeya Dwivedi 	 */
8235f14dbdSKumar Kartikeya Dwivedi 	return 0;
8335f14dbdSKumar Kartikeya Dwivedi }
8435f14dbdSKumar Kartikeya Dwivedi 
8535f14dbdSKumar Kartikeya Dwivedi SEC("?tc")
nested_cb(void * ctx)8635f14dbdSKumar Kartikeya Dwivedi int nested_cb(void *ctx)
8735f14dbdSKumar Kartikeya Dwivedi {
8835f14dbdSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
8935f14dbdSKumar Kartikeya Dwivedi 	unsigned long sl = 0;
9035f14dbdSKumar Kartikeya Dwivedi 	int sp = 0;
9135f14dbdSKumar Kartikeya Dwivedi 
9235f14dbdSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&sl);
9335f14dbdSKumar Kartikeya Dwivedi 	if (!p)
9435f14dbdSKumar Kartikeya Dwivedi 		return 0;
9535f14dbdSKumar Kartikeya Dwivedi 	bpf_for_each_map_elem(&array_map, cb3, &sp, 0);
9635f14dbdSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_release(p);
9735f14dbdSKumar Kartikeya Dwivedi 	return 0;
9835f14dbdSKumar Kartikeya Dwivedi }
9935f14dbdSKumar Kartikeya Dwivedi 
10035f14dbdSKumar Kartikeya Dwivedi SEC("?tc")
non_cb_transfer_ref(void * ctx)10135f14dbdSKumar Kartikeya Dwivedi int non_cb_transfer_ref(void *ctx)
10235f14dbdSKumar Kartikeya Dwivedi {
10335f14dbdSKumar Kartikeya Dwivedi 	struct prog_test_ref_kfunc *p;
10435f14dbdSKumar Kartikeya Dwivedi 	unsigned long sl = 0;
10535f14dbdSKumar Kartikeya Dwivedi 
10635f14dbdSKumar Kartikeya Dwivedi 	p = bpf_kfunc_call_test_acquire(&sl);
10735f14dbdSKumar Kartikeya Dwivedi 	if (!p)
10835f14dbdSKumar Kartikeya Dwivedi 		return 0;
10935f14dbdSKumar Kartikeya Dwivedi 	cb1(NULL, NULL, NULL, &p);
11035f14dbdSKumar Kartikeya Dwivedi 	bpf_kfunc_call_test_acquire(&sl);
11135f14dbdSKumar Kartikeya Dwivedi 	return 0;
11235f14dbdSKumar Kartikeya Dwivedi }
11335f14dbdSKumar Kartikeya Dwivedi 
11435f14dbdSKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
115