]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/progs/cb_refs.c
Linux 6.14-rc3
[linux.git] / tools / testing / selftests / bpf / progs / cb_refs.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <vmlinux.h>
3 #include <bpf/bpf_tracing.h>
4 #include <bpf/bpf_helpers.h>
5 #include "../test_kmods/bpf_testmod_kfunc.h"
6
7 struct map_value {
8         struct prog_test_ref_kfunc __kptr *ptr;
9 };
10
11 struct {
12         __uint(type, BPF_MAP_TYPE_ARRAY);
13         __type(key, int);
14         __type(value, struct map_value);
15         __uint(max_entries, 16);
16 } array_map SEC(".maps");
17
18 static __noinline int cb1(void *map, void *key, void *value, void *ctx)
19 {
20         void *p = *(void **)ctx;
21         bpf_kfunc_call_test_release(p);
22         /* Without the fix this would cause underflow */
23         return 0;
24 }
25
26 SEC("?tc")
27 int underflow_prog(void *ctx)
28 {
29         struct prog_test_ref_kfunc *p;
30         unsigned long sl = 0;
31
32         p = bpf_kfunc_call_test_acquire(&sl);
33         if (!p)
34                 return 0;
35         bpf_for_each_map_elem(&array_map, cb1, &p, 0);
36         bpf_kfunc_call_test_release(p);
37         return 0;
38 }
39
40 static __always_inline int cb2(void *map, void *key, void *value, void *ctx)
41 {
42         unsigned long sl = 0;
43
44         *(void **)ctx = bpf_kfunc_call_test_acquire(&sl);
45         /* Without the fix this would leak memory */
46         return 0;
47 }
48
49 SEC("?tc")
50 int leak_prog(void *ctx)
51 {
52         struct prog_test_ref_kfunc *p;
53         struct map_value *v;
54
55         v = bpf_map_lookup_elem(&array_map, &(int){0});
56         if (!v)
57                 return 0;
58
59         p = NULL;
60         bpf_for_each_map_elem(&array_map, cb2, &p, 0);
61         p = bpf_kptr_xchg(&v->ptr, p);
62         if (p)
63                 bpf_kfunc_call_test_release(p);
64         return 0;
65 }
66
67 static __always_inline int cb(void *map, void *key, void *value, void *ctx)
68 {
69         return 0;
70 }
71
72 static __always_inline int cb3(void *map, void *key, void *value, void *ctx)
73 {
74         unsigned long sl = 0;
75         void *p;
76
77         bpf_kfunc_call_test_acquire(&sl);
78         bpf_for_each_map_elem(&array_map, cb, &p, 0);
79         /* It should only complain here, not in cb. This is why we need
80          * callback_ref to be set to frameno.
81          */
82         return 0;
83 }
84
85 SEC("?tc")
86 int nested_cb(void *ctx)
87 {
88         struct prog_test_ref_kfunc *p;
89         unsigned long sl = 0;
90         int sp = 0;
91
92         p = bpf_kfunc_call_test_acquire(&sl);
93         if (!p)
94                 return 0;
95         bpf_for_each_map_elem(&array_map, cb3, &sp, 0);
96         bpf_kfunc_call_test_release(p);
97         return 0;
98 }
99
100 SEC("?tc")
101 int non_cb_transfer_ref(void *ctx)
102 {
103         struct prog_test_ref_kfunc *p;
104         unsigned long sl = 0;
105
106         p = bpf_kfunc_call_test_acquire(&sl);
107         if (!p)
108                 return 0;
109         cb1(NULL, NULL, NULL, &p);
110         bpf_kfunc_call_test_acquire(&sl);
111         return 0;
112 }
113
114 char _license[] SEC("license") = "GPL";
This page took 0.038395 seconds and 4 git commands to generate.