~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/progs/local_kptr_stash.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
  3 
  4 #include <vmlinux.h>
  5 #include <bpf/bpf_tracing.h>
  6 #include <bpf/bpf_helpers.h>
  7 #include <bpf/bpf_core_read.h>
  8 #include "../bpf_experimental.h"
  9 #include "../bpf_testmod/bpf_testmod_kfunc.h"
 10 
 11 struct node_data {
 12         long key;
 13         long data;
 14         struct bpf_rb_node node;
 15 };
 16 
 17 struct refcounted_node {
 18         long data;
 19         struct bpf_rb_node rb_node;
 20         struct bpf_refcount refcount;
 21 };
 22 
 23 struct stash {
 24         struct bpf_spin_lock l;
 25         struct refcounted_node __kptr *stashed;
 26 };
 27 
 28 struct {
 29         __uint(type, BPF_MAP_TYPE_ARRAY);
 30         __type(key, int);
 31         __type(value, struct stash);
 32         __uint(max_entries, 10);
 33 } refcounted_node_stash SEC(".maps");
 34 
 35 struct plain_local {
 36         long key;
 37         long data;
 38 };
 39 
 40 struct local_with_root {
 41         long key;
 42         struct bpf_spin_lock l;
 43         struct bpf_rb_root r __contains(node_data, node);
 44 };
 45 
 46 struct map_value {
 47         struct prog_test_ref_kfunc *not_kptr;
 48         struct prog_test_ref_kfunc __kptr *val;
 49         struct node_data __kptr *node;
 50         struct plain_local __kptr *plain;
 51         struct local_with_root __kptr *local_root;
 52 };
 53 
 54 /* This is necessary so that LLVM generates BTF for node_data struct
 55  * If it's not included, a fwd reference for node_data will be generated but
 56  * no struct. Example BTF of "node" field in map_value when not included:
 57  *
 58  * [10] PTR '(anon)' type_id=35
 59  * [34] FWD 'node_data' fwd_kind=struct
 60  * [35] TYPE_TAG 'kptr_ref' type_id=34
 61  *
 62  * (with no node_data struct defined)
 63  * Had to do the same w/ bpf_kfunc_call_test_release below
 64  */
 65 struct node_data *just_here_because_btf_bug;
 66 struct refcounted_node *just_here_because_btf_bug2;
 67 
 68 struct {
 69         __uint(type, BPF_MAP_TYPE_ARRAY);
 70         __type(key, int);
 71         __type(value, struct map_value);
 72         __uint(max_entries, 2);
 73 } some_nodes SEC(".maps");
 74 
 75 static bool less(struct bpf_rb_node *a, const struct bpf_rb_node *b)
 76 {
 77         struct node_data *node_a;
 78         struct node_data *node_b;
 79 
 80         node_a = container_of(a, struct node_data, node);
 81         node_b = container_of(b, struct node_data, node);
 82 
 83         return node_a->key < node_b->key;
 84 }
 85 
 86 static int create_and_stash(int idx, int val)
 87 {
 88         struct map_value *mapval;
 89         struct node_data *res;
 90 
 91         mapval = bpf_map_lookup_elem(&some_nodes, &idx);
 92         if (!mapval)
 93                 return 1;
 94 
 95         res = bpf_obj_new(typeof(*res));
 96         if (!res)
 97                 return 1;
 98         res->key = val;
 99 
100         res = bpf_kptr_xchg(&mapval->node, res);
101         if (res)
102                 bpf_obj_drop(res);
103         return 0;
104 }
105 
106 SEC("tc")
107 long stash_rb_nodes(void *ctx)
108 {
109         return create_and_stash(0, 41) ?: create_and_stash(1, 42);
110 }
111 
112 SEC("tc")
113 long stash_plain(void *ctx)
114 {
115         struct map_value *mapval;
116         struct plain_local *res;
117         int idx = 0;
118 
119         mapval = bpf_map_lookup_elem(&some_nodes, &idx);
120         if (!mapval)
121                 return 1;
122 
123         res = bpf_obj_new(typeof(*res));
124         if (!res)
125                 return 1;
126         res->key = 41;
127 
128         res = bpf_kptr_xchg(&mapval->plain, res);
129         if (res)
130                 bpf_obj_drop(res);
131         return 0;
132 }
133 
134 SEC("tc")
135 long stash_local_with_root(void *ctx)
136 {
137         struct local_with_root *res;
138         struct map_value *mapval;
139         struct node_data *n;
140         int idx = 0;
141 
142         mapval = bpf_map_lookup_elem(&some_nodes, &idx);
143         if (!mapval)
144                 return 1;
145 
146         res = bpf_obj_new(typeof(*res));
147         if (!res)
148                 return 2;
149         res->key = 41;
150 
151         n = bpf_obj_new(typeof(*n));
152         if (!n) {
153                 bpf_obj_drop(res);
154                 return 3;
155         }
156 
157         bpf_spin_lock(&res->l);
158         bpf_rbtree_add(&res->r, &n->node, less);
159         bpf_spin_unlock(&res->l);
160 
161         res = bpf_kptr_xchg(&mapval->local_root, res);
162         if (res) {
163                 bpf_obj_drop(res);
164                 return 4;
165         }
166         return 0;
167 }
168 
169 SEC("tc")
170 long unstash_rb_node(void *ctx)
171 {
172         struct map_value *mapval;
173         struct node_data *res;
174         long retval;
175         int key = 1;
176 
177         mapval = bpf_map_lookup_elem(&some_nodes, &key);
178         if (!mapval)
179                 return 1;
180 
181         res = bpf_kptr_xchg(&mapval->node, NULL);
182         if (res) {
183                 retval = res->key;
184                 bpf_obj_drop(res);
185                 return retval;
186         }
187         return 1;
188 }
189 
190 SEC("tc")
191 long stash_test_ref_kfunc(void *ctx)
192 {
193         struct prog_test_ref_kfunc *res;
194         struct map_value *mapval;
195         int key = 0;
196 
197         mapval = bpf_map_lookup_elem(&some_nodes, &key);
198         if (!mapval)
199                 return 1;
200 
201         res = bpf_kptr_xchg(&mapval->val, NULL);
202         if (res)
203                 bpf_kfunc_call_test_release(res);
204         return 0;
205 }
206 
207 SEC("tc")
208 long refcount_acquire_without_unstash(void *ctx)
209 {
210         struct refcounted_node *p;
211         struct stash *s;
212         int ret = 0;
213 
214         s = bpf_map_lookup_elem(&refcounted_node_stash, &ret);
215         if (!s)
216                 return 1;
217 
218         if (!s->stashed)
219                 /* refcount_acquire failure is expected when no refcounted_node
220                  * has been stashed before this program executes
221                  */
222                 return 2;
223 
224         p = bpf_refcount_acquire(s->stashed);
225         if (!p)
226                 return 3;
227 
228         ret = s->stashed ? s->stashed->data : -1;
229         bpf_obj_drop(p);
230         return ret;
231 }
232 
233 /* Helper for refcount_acquire_without_unstash test */
234 SEC("tc")
235 long stash_refcounted_node(void *ctx)
236 {
237         struct refcounted_node *p;
238         struct stash *s;
239         int key = 0;
240 
241         s = bpf_map_lookup_elem(&refcounted_node_stash, &key);
242         if (!s)
243                 return 1;
244 
245         p = bpf_obj_new(typeof(*p));
246         if (!p)
247                 return 2;
248         p->data = 42;
249 
250         p = bpf_kptr_xchg(&s->stashed, p);
251         if (p) {
252                 bpf_obj_drop(p);
253                 return 3;
254         }
255 
256         return 0;
257 }
258 
259 char _license[] SEC("license") = "GPL";
260 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php