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/bpf_core_read.h>
6 #include "bpf_experimental.h"
7 #include "bpf_misc.h"
8 
9 struct node_acquire {
10 	long key;
11 	long data;
12 	struct bpf_rb_node node;
13 	struct bpf_refcount refcount;
14 };
15 
16 #define private(name) SEC(".data." #name) __hidden __attribute__((aligned(8)))
17 private(A) struct bpf_spin_lock glock;
18 private(A) struct bpf_rb_root groot __contains(node_acquire, node);
19 
20 static bool less(struct bpf_rb_node *a, const struct bpf_rb_node *b)
21 {
22 	struct node_acquire *node_a;
23 	struct node_acquire *node_b;
24 
25 	node_a = container_of(a, struct node_acquire, node);
26 	node_b = container_of(b, struct node_acquire, node);
27 
28 	return node_a->key < node_b->key;
29 }
30 
31 SEC("?tc")
32 __failure __msg("Unreleased reference id=4 alloc_insn=21")
33 long rbtree_refcounted_node_ref_escapes(void *ctx)
34 {
35 	struct node_acquire *n, *m;
36 
37 	n = bpf_obj_new(typeof(*n));
38 	if (!n)
39 		return 1;
40 
41 	bpf_spin_lock(&glock);
42 	bpf_rbtree_add(&groot, &n->node, less);
43 	/* m becomes an owning ref but is never drop'd or added to a tree */
44 	m = bpf_refcount_acquire(n);
45 	bpf_spin_unlock(&glock);
46 	if (!m)
47 		return 2;
48 
49 	m->key = 2;
50 	return 0;
51 }
52 
53 SEC("?tc")
54 __failure __msg("Unreleased reference id=3 alloc_insn=9")
55 long rbtree_refcounted_node_ref_escapes_owning_input(void *ctx)
56 {
57 	struct node_acquire *n, *m;
58 
59 	n = bpf_obj_new(typeof(*n));
60 	if (!n)
61 		return 1;
62 
63 	/* m becomes an owning ref but is never drop'd or added to a tree */
64 	m = bpf_refcount_acquire(n);
65 	m->key = 2;
66 
67 	bpf_spin_lock(&glock);
68 	bpf_rbtree_add(&groot, &n->node, less);
69 	bpf_spin_unlock(&glock);
70 
71 	return 0;
72 }
73 
74 char _license[] SEC("license") = "GPL";
75