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_experimental.h" 6 7struct foo { 8 struct bpf_spin_lock lock; 9 int data; 10}; 11 12struct array_map { 13 __uint(type, BPF_MAP_TYPE_ARRAY); 14 __type(key, int); 15 __type(value, struct foo); 16 __uint(max_entries, 1); 17} array_map SEC(".maps"); 18 19struct { 20 __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); 21 __uint(max_entries, 1); 22 __type(key, int); 23 __type(value, int); 24 __array(values, struct array_map); 25} map_of_maps SEC(".maps") = { 26 .values = { 27 [0] = &array_map, 28 }, 29}; 30 31SEC(".data.A") struct bpf_spin_lock lockA; 32SEC(".data.B") struct bpf_spin_lock lockB; 33 34SEC("?tc") 35int lock_id_kptr_preserve(void *ctx) 36{ 37 struct foo *f; 38 39 f = bpf_obj_new(typeof(*f)); 40 if (!f) 41 return 0; 42 bpf_this_cpu_ptr(f); 43 return 0; 44} 45 46SEC("?tc") 47int lock_id_global_zero(void *ctx) 48{ 49 bpf_this_cpu_ptr(&lockA); 50 return 0; 51} 52 53SEC("?tc") 54int lock_id_mapval_preserve(void *ctx) 55{ 56 struct foo *f; 57 int key = 0; 58 59 f = bpf_map_lookup_elem(&array_map, &key); 60 if (!f) 61 return 0; 62 bpf_this_cpu_ptr(f); 63 return 0; 64} 65 66SEC("?tc") 67int lock_id_innermapval_preserve(void *ctx) 68{ 69 struct foo *f; 70 int key = 0; 71 void *map; 72 73 map = bpf_map_lookup_elem(&map_of_maps, &key); 74 if (!map) 75 return 0; 76 f = bpf_map_lookup_elem(map, &key); 77 if (!f) 78 return 0; 79 bpf_this_cpu_ptr(f); 80 return 0; 81} 82 83#define CHECK(test, A, B) \ 84 SEC("?tc") \ 85 int lock_id_mismatch_##test(void *ctx) \ 86 { \ 87 struct foo *f1, *f2, *v, *iv; \ 88 int key = 0; \ 89 void *map; \ 90 \ 91 map = bpf_map_lookup_elem(&map_of_maps, &key); \ 92 if (!map) \ 93 return 0; \ 94 iv = bpf_map_lookup_elem(map, &key); \ 95 if (!iv) \ 96 return 0; \ 97 v = bpf_map_lookup_elem(&array_map, &key); \ 98 if (!v) \ 99 return 0; \ 100 f1 = bpf_obj_new(typeof(*f1)); \ 101 if (!f1) \ 102 return 0; \ 103 f2 = bpf_obj_new(typeof(*f2)); \ 104 if (!f2) { \ 105 bpf_obj_drop(f1); \ 106 return 0; \ 107 } \ 108 bpf_spin_lock(A); \ 109 bpf_spin_unlock(B); \ 110 return 0; \ 111 } 112 113CHECK(kptr_kptr, &f1->lock, &f2->lock); 114CHECK(kptr_global, &f1->lock, &lockA); 115CHECK(kptr_mapval, &f1->lock, &v->lock); 116CHECK(kptr_innermapval, &f1->lock, &iv->lock); 117 118CHECK(global_global, &lockA, &lockB); 119CHECK(global_kptr, &lockA, &f1->lock); 120CHECK(global_mapval, &lockA, &v->lock); 121CHECK(global_innermapval, &lockA, &iv->lock); 122 123SEC("?tc") 124int lock_id_mismatch_mapval_mapval(void *ctx) 125{ 126 struct foo *f1, *f2; 127 int key = 0; 128 129 f1 = bpf_map_lookup_elem(&array_map, &key); 130 if (!f1) 131 return 0; 132 f2 = bpf_map_lookup_elem(&array_map, &key); 133 if (!f2) 134 return 0; 135 136 bpf_spin_lock(&f1->lock); 137 f1->data = 42; 138 bpf_spin_unlock(&f2->lock); 139 140 return 0; 141} 142 143CHECK(mapval_kptr, &v->lock, &f1->lock); 144CHECK(mapval_global, &v->lock, &lockB); 145CHECK(mapval_innermapval, &v->lock, &iv->lock); 146 147SEC("?tc") 148int lock_id_mismatch_innermapval_innermapval1(void *ctx) 149{ 150 struct foo *f1, *f2; 151 int key = 0; 152 void *map; 153 154 map = bpf_map_lookup_elem(&map_of_maps, &key); 155 if (!map) 156 return 0; 157 f1 = bpf_map_lookup_elem(map, &key); 158 if (!f1) 159 return 0; 160 f2 = bpf_map_lookup_elem(map, &key); 161 if (!f2) 162 return 0; 163 164 bpf_spin_lock(&f1->lock); 165 f1->data = 42; 166 bpf_spin_unlock(&f2->lock); 167 168 return 0; 169} 170 171SEC("?tc") 172int lock_id_mismatch_innermapval_innermapval2(void *ctx) 173{ 174 struct foo *f1, *f2; 175 int key = 0; 176 void *map; 177 178 map = bpf_map_lookup_elem(&map_of_maps, &key); 179 if (!map) 180 return 0; 181 f1 = bpf_map_lookup_elem(map, &key); 182 if (!f1) 183 return 0; 184 map = bpf_map_lookup_elem(&map_of_maps, &key); 185 if (!map) 186 return 0; 187 f2 = bpf_map_lookup_elem(map, &key); 188 if (!f2) 189 return 0; 190 191 bpf_spin_lock(&f1->lock); 192 f1->data = 42; 193 bpf_spin_unlock(&f2->lock); 194 195 return 0; 196} 197 198CHECK(innermapval_kptr, &iv->lock, &f1->lock); 199CHECK(innermapval_global, &iv->lock, &lockA); 200CHECK(innermapval_mapval, &iv->lock, &v->lock); 201 202#undef CHECK 203 204__noinline 205int global_subprog(struct __sk_buff *ctx) 206{ 207 volatile int ret = 0; 208 209 if (ctx->protocol) 210 ret += ctx->protocol; 211 return ret + ctx->mark; 212} 213 214__noinline 215static int static_subprog_call_global(struct __sk_buff *ctx) 216{ 217 volatile int ret = 0; 218 219 if (ctx->protocol) 220 return ret; 221 return ret + ctx->len + global_subprog(ctx); 222} 223 224SEC("?tc") 225int lock_global_subprog_call1(struct __sk_buff *ctx) 226{ 227 int ret = 0; 228 229 bpf_spin_lock(&lockA); 230 if (ctx->mark == 42) 231 ret = global_subprog(ctx); 232 bpf_spin_unlock(&lockA); 233 return ret; 234} 235 236SEC("?tc") 237int lock_global_subprog_call2(struct __sk_buff *ctx) 238{ 239 int ret = 0; 240 241 bpf_spin_lock(&lockA); 242 if (ctx->mark == 42) 243 ret = static_subprog_call_global(ctx); 244 bpf_spin_unlock(&lockA); 245 return ret; 246} 247 248char _license[] SEC("license") = "GPL"; 249