File Index
Files and directories
Sign in
FILE

res_spin_lock_fail.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/res_spin_lock_fail.c C
  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";
~/ Read-only file preview.