115 lines · c
1// SPDX-License-Identifier: GPL-2.02#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 need80 * 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";115