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