249 lines · c
1// SPDX-License-Identifier: GPL-2.02#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 CHECK203 204__noinline205int 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__noinline215static 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