Linux Audio

Check our new training course

Loading...
v6.13.7
  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";
v6.2
  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";