Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 244 lines 5.4 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (c) 2024-2025 Meta Platforms, Inc. and affiliates. */ 3#include <vmlinux.h> 4#include <bpf/bpf_tracing.h> 5#include <bpf/bpf_helpers.h> 6#include <bpf/bpf_core_read.h> 7#include "bpf_misc.h" 8#include "bpf_experimental.h" 9 10struct arr_elem { 11 struct bpf_res_spin_lock lock; 12}; 13 14struct { 15 __uint(type, BPF_MAP_TYPE_ARRAY); 16 __uint(max_entries, 1); 17 __type(key, int); 18 __type(value, struct arr_elem); 19} arrmap SEC(".maps"); 20 21long value; 22 23struct bpf_spin_lock lock __hidden SEC(".data.A"); 24struct bpf_res_spin_lock res_lock __hidden SEC(".data.B"); 25 26SEC("?tc") 27__failure __msg("point to map value or allocated object") 28int res_spin_lock_arg(struct __sk_buff *ctx) 29{ 30 struct arr_elem *elem; 31 32 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 33 if (!elem) 34 return 0; 35 bpf_res_spin_lock((struct bpf_res_spin_lock *)bpf_core_cast(&elem->lock, struct __sk_buff)); 36 bpf_res_spin_lock(&elem->lock); 37 return 0; 38} 39 40SEC("?tc") 41__failure __msg("AA deadlock detected") 42int res_spin_lock_AA(struct __sk_buff *ctx) 43{ 44 struct arr_elem *elem; 45 46 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 47 if (!elem) 48 return 0; 49 bpf_res_spin_lock(&elem->lock); 50 bpf_res_spin_lock(&elem->lock); 51 return 0; 52} 53 54SEC("?tc") 55__failure __msg("AA deadlock detected") 56int res_spin_lock_cond_AA(struct __sk_buff *ctx) 57{ 58 struct arr_elem *elem; 59 60 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 61 if (!elem) 62 return 0; 63 if (bpf_res_spin_lock(&elem->lock)) 64 return 0; 65 bpf_res_spin_lock(&elem->lock); 66 return 0; 67} 68 69SEC("?tc") 70__failure __msg("unlock of different lock") 71int res_spin_lock_mismatch_1(struct __sk_buff *ctx) 72{ 73 struct arr_elem *elem; 74 75 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 76 if (!elem) 77 return 0; 78 if (bpf_res_spin_lock(&elem->lock)) 79 return 0; 80 bpf_res_spin_unlock(&res_lock); 81 return 0; 82} 83 84SEC("?tc") 85__failure __msg("unlock of different lock") 86int res_spin_lock_mismatch_2(struct __sk_buff *ctx) 87{ 88 struct arr_elem *elem; 89 90 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 91 if (!elem) 92 return 0; 93 if (bpf_res_spin_lock(&res_lock)) 94 return 0; 95 bpf_res_spin_unlock(&elem->lock); 96 return 0; 97} 98 99SEC("?tc") 100__failure __msg("unlock of different lock") 101int res_spin_lock_irq_mismatch_1(struct __sk_buff *ctx) 102{ 103 struct arr_elem *elem; 104 unsigned long f1; 105 106 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 107 if (!elem) 108 return 0; 109 bpf_local_irq_save(&f1); 110 if (bpf_res_spin_lock(&res_lock)) 111 return 0; 112 bpf_res_spin_unlock_irqrestore(&res_lock, &f1); 113 return 0; 114} 115 116SEC("?tc") 117__failure __msg("unlock of different lock") 118int res_spin_lock_irq_mismatch_2(struct __sk_buff *ctx) 119{ 120 struct arr_elem *elem; 121 unsigned long f1; 122 123 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 124 if (!elem) 125 return 0; 126 if (bpf_res_spin_lock_irqsave(&res_lock, &f1)) 127 return 0; 128 bpf_res_spin_unlock(&res_lock); 129 return 0; 130} 131 132SEC("?tc") 133__success 134int res_spin_lock_ooo(struct __sk_buff *ctx) 135{ 136 struct arr_elem *elem; 137 138 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 139 if (!elem) 140 return 0; 141 if (bpf_res_spin_lock(&res_lock)) 142 return 0; 143 if (bpf_res_spin_lock(&elem->lock)) { 144 bpf_res_spin_unlock(&res_lock); 145 return 0; 146 } 147 bpf_res_spin_unlock(&elem->lock); 148 bpf_res_spin_unlock(&res_lock); 149 return 0; 150} 151 152SEC("?tc") 153__success 154int res_spin_lock_ooo_irq(struct __sk_buff *ctx) 155{ 156 struct arr_elem *elem; 157 unsigned long f1, f2; 158 159 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 160 if (!elem) 161 return 0; 162 if (bpf_res_spin_lock_irqsave(&res_lock, &f1)) 163 return 0; 164 if (bpf_res_spin_lock_irqsave(&elem->lock, &f2)) { 165 bpf_res_spin_unlock_irqrestore(&res_lock, &f1); 166 /* We won't have a unreleased IRQ flag error here. */ 167 return 0; 168 } 169 bpf_res_spin_unlock_irqrestore(&elem->lock, &f2); 170 bpf_res_spin_unlock_irqrestore(&res_lock, &f1); 171 return 0; 172} 173 174struct bpf_res_spin_lock lock1 __hidden SEC(".data.OO1"); 175struct bpf_res_spin_lock lock2 __hidden SEC(".data.OO2"); 176 177SEC("?tc") 178__failure __msg("bpf_res_spin_unlock cannot be out of order") 179int res_spin_lock_ooo_unlock(struct __sk_buff *ctx) 180{ 181 if (bpf_res_spin_lock(&lock1)) 182 return 0; 183 if (bpf_res_spin_lock(&lock2)) { 184 bpf_res_spin_unlock(&lock1); 185 return 0; 186 } 187 bpf_res_spin_unlock(&lock1); 188 bpf_res_spin_unlock(&lock2); 189 return 0; 190} 191 192SEC("?tc") 193__failure __msg("off 1 doesn't point to 'struct bpf_res_spin_lock' that is at 0") 194int res_spin_lock_bad_off(struct __sk_buff *ctx) 195{ 196 struct arr_elem *elem; 197 198 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 199 if (!elem) 200 return 0; 201 bpf_res_spin_lock((void *)&elem->lock + 1); 202 return 0; 203} 204 205SEC("?tc") 206__failure __msg("R1 doesn't have constant offset. bpf_res_spin_lock has to be at the constant offset") 207int res_spin_lock_var_off(struct __sk_buff *ctx) 208{ 209 struct arr_elem *elem; 210 u64 val = value; 211 212 elem = bpf_map_lookup_elem(&arrmap, &(int){0}); 213 if (!elem) { 214 // FIXME: Only inline assembly use in assert macro doesn't emit 215 // BTF definition. 216 bpf_throw(0); 217 return 0; 218 } 219 bpf_assert_range(val, 0, 40); 220 bpf_res_spin_lock((void *)&value + val); 221 return 0; 222} 223 224SEC("?tc") 225__failure __msg("map 'res_spin.bss' has no valid bpf_res_spin_lock") 226int res_spin_lock_no_lock_map(struct __sk_buff *ctx) 227{ 228 bpf_res_spin_lock((void *)&value + 1); 229 return 0; 230} 231 232SEC("?tc") 233__failure __msg("local 'kptr' has no valid bpf_res_spin_lock") 234int res_spin_lock_no_lock_kptr(struct __sk_buff *ctx) 235{ 236 struct { int i; } *p = bpf_obj_new(typeof(*p)); 237 238 if (!p) 239 return 0; 240 bpf_res_spin_lock((void *)p); 241 return 0; 242} 243 244char _license[] SEC("license") = "GPL";