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_helpers.h> 6 #include <bpf/bpf_tracing.h> 7 #include <bpf/bpf_core_read.h> 8 #include "../bpf_experimental.h" 9 #include "bpf_misc.h" 10 11 struct node_data { 12 long key; 13 long data; 14 struct bpf_rb_node node; 15 }; 16 17 struct map_value { 18 struct node_data __kptr *node; 19 }; 20 21 struct node_data2 { 22 long key[4]; 23 }; 24 25 /* This is necessary so that LLVM generates BTF for node_data struct 26 * If it's not included, a fwd reference for node_data will be generated but 27 * no struct. Example BTF of "node" field in map_value when not included: 28 * 29 * [10] PTR '(anon)' type_id=35 30 * [34] FWD 'node_data' fwd_kind=struct 31 * [35] TYPE_TAG 'kptr_ref' type_id=34 32 */ 33 struct node_data *just_here_because_btf_bug; 34 35 struct { 36 __uint(type, BPF_MAP_TYPE_ARRAY); 37 __type(key, int); 38 __type(value, struct map_value); 39 __uint(max_entries, 2); 40 } some_nodes SEC(".maps"); 41 42 SEC("tc") 43 __failure __msg("invalid kptr access, R2 type=ptr_node_data2 expected=ptr_node_data") 44 long stash_rb_nodes(void *ctx) 45 { 46 struct map_value *mapval; 47 struct node_data2 *res; 48 int idx = 0; 49 50 mapval = bpf_map_lookup_elem(&some_nodes, &idx); 51 if (!mapval) 52 return 1; 53 54 res = bpf_obj_new(typeof(*res)); 55 if (!res) 56 return 1; 57 res->key[0] = 40; 58 59 res = bpf_kptr_xchg(&mapval->node, res); 60 if (res) 61 bpf_obj_drop(res); 62 return 0; 63 } 64 65 SEC("tc") 66 __failure __msg("R1 must have zero offset when passed to release func") 67 long drop_rb_node_off(void *ctx) 68 { 69 struct map_value *mapval; 70 struct node_data *res; 71 int idx = 0; 72 73 mapval = bpf_map_lookup_elem(&some_nodes, &idx); 74 if (!mapval) 75 return 1; 76 77 res = bpf_obj_new(typeof(*res)); 78 if (!res) 79 return 1; 80 /* Try releasing with graph node offset */ 81 bpf_obj_drop(&res->node); 82 return 0; 83 } 84 85 char _license[] SEC("license") = "GPL"; 86