1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
4 #include <bpf/bpf_helpers.h>
6 #include "bpf_experimental.h"
8 unsigned long global_flags;
10 extern void bpf_local_irq_save(unsigned long *) __weak __ksym;
11 extern void bpf_local_irq_restore(unsigned long *) __weak __ksym;
12 extern int bpf_copy_from_user_str(void *dst, u32 dst__sz, const void *unsafe_ptr__ign, u64 flags) __weak __ksym;
15 __failure __msg("arg#0 doesn't point to an irq flag on stack")
16 int irq_save_bad_arg(struct __sk_buff *ctx)
18 bpf_local_irq_save(&global_flags);
23 __failure __msg("arg#0 doesn't point to an irq flag on stack")
24 int irq_restore_bad_arg(struct __sk_buff *ctx)
26 bpf_local_irq_restore(&global_flags);
31 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region")
32 int irq_restore_missing_2(struct __sk_buff *ctx)
37 bpf_local_irq_save(&flags1);
38 bpf_local_irq_save(&flags2);
43 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region")
44 int irq_restore_missing_3(struct __sk_buff *ctx)
50 bpf_local_irq_save(&flags1);
51 bpf_local_irq_save(&flags2);
52 bpf_local_irq_save(&flags3);
57 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region")
58 int irq_restore_missing_3_minus_2(struct __sk_buff *ctx)
64 bpf_local_irq_save(&flags1);
65 bpf_local_irq_save(&flags2);
66 bpf_local_irq_save(&flags3);
67 bpf_local_irq_restore(&flags3);
68 bpf_local_irq_restore(&flags2);
72 static __noinline void local_irq_save(unsigned long *flags)
74 bpf_local_irq_save(flags);
77 static __noinline void local_irq_restore(unsigned long *flags)
79 bpf_local_irq_restore(flags);
83 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region")
84 int irq_restore_missing_1_subprog(struct __sk_buff *ctx)
88 local_irq_save(&flags);
93 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region")
94 int irq_restore_missing_2_subprog(struct __sk_buff *ctx)
99 local_irq_save(&flags1);
100 local_irq_save(&flags2);
105 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region")
106 int irq_restore_missing_3_subprog(struct __sk_buff *ctx)
108 unsigned long flags1;
109 unsigned long flags2;
110 unsigned long flags3;
112 local_irq_save(&flags1);
113 local_irq_save(&flags2);
114 local_irq_save(&flags3);
119 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_local_irq_save-ed region")
120 int irq_restore_missing_3_minus_2_subprog(struct __sk_buff *ctx)
122 unsigned long flags1;
123 unsigned long flags2;
124 unsigned long flags3;
126 local_irq_save(&flags1);
127 local_irq_save(&flags2);
128 local_irq_save(&flags3);
129 local_irq_restore(&flags3);
130 local_irq_restore(&flags2);
136 int irq_balance(struct __sk_buff *ctx)
140 local_irq_save(&flags);
141 local_irq_restore(&flags);
147 int irq_balance_n(struct __sk_buff *ctx)
149 unsigned long flags1;
150 unsigned long flags2;
151 unsigned long flags3;
153 local_irq_save(&flags1);
154 local_irq_save(&flags2);
155 local_irq_save(&flags3);
156 local_irq_restore(&flags3);
157 local_irq_restore(&flags2);
158 local_irq_restore(&flags1);
162 static __noinline void local_irq_balance(void)
166 local_irq_save(&flags);
167 local_irq_restore(&flags);
170 static __noinline void local_irq_balance_n(void)
172 unsigned long flags1;
173 unsigned long flags2;
174 unsigned long flags3;
176 local_irq_save(&flags1);
177 local_irq_save(&flags2);
178 local_irq_save(&flags3);
179 local_irq_restore(&flags3);
180 local_irq_restore(&flags2);
181 local_irq_restore(&flags1);
186 int irq_balance_subprog(struct __sk_buff *ctx)
192 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
193 __failure __msg("sleepable helper bpf_copy_from_user#")
194 int irq_sleepable_helper(void *ctx)
199 local_irq_save(&flags);
200 bpf_copy_from_user(&data, sizeof(data), NULL);
201 local_irq_restore(&flags);
205 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
206 __failure __msg("kernel func bpf_copy_from_user_str is sleepable within IRQ-disabled region")
207 int irq_sleepable_kfunc(void *ctx)
212 local_irq_save(&flags);
213 bpf_copy_from_user_str(&data, sizeof(data), NULL, 0);
214 local_irq_restore(&flags);
218 int __noinline global_local_irq_balance(void)
220 local_irq_balance_n();
225 __failure __msg("global function calls are not allowed with IRQs disabled")
226 int irq_global_subprog(struct __sk_buff *ctx)
230 bpf_local_irq_save(&flags);
231 global_local_irq_balance();
232 bpf_local_irq_restore(&flags);
237 __failure __msg("cannot restore irq state out of order")
238 int irq_restore_ooo(struct __sk_buff *ctx)
240 unsigned long flags1;
241 unsigned long flags2;
243 bpf_local_irq_save(&flags1);
244 bpf_local_irq_save(&flags2);
245 bpf_local_irq_restore(&flags1);
246 bpf_local_irq_restore(&flags2);
251 __failure __msg("cannot restore irq state out of order")
252 int irq_restore_ooo_3(struct __sk_buff *ctx)
254 unsigned long flags1;
255 unsigned long flags2;
256 unsigned long flags3;
258 bpf_local_irq_save(&flags1);
259 bpf_local_irq_save(&flags2);
260 bpf_local_irq_restore(&flags2);
261 bpf_local_irq_save(&flags3);
262 bpf_local_irq_restore(&flags1);
263 bpf_local_irq_restore(&flags3);
267 static __noinline void local_irq_save_3(unsigned long *flags1, unsigned long *flags2,
268 unsigned long *flags3)
270 local_irq_save(flags1);
271 local_irq_save(flags2);
272 local_irq_save(flags3);
277 int irq_restore_3_subprog(struct __sk_buff *ctx)
279 unsigned long flags1;
280 unsigned long flags2;
281 unsigned long flags3;
283 local_irq_save_3(&flags1, &flags2, &flags3);
284 bpf_local_irq_restore(&flags3);
285 bpf_local_irq_restore(&flags2);
286 bpf_local_irq_restore(&flags1);
291 __failure __msg("cannot restore irq state out of order")
292 int irq_restore_4_subprog(struct __sk_buff *ctx)
294 unsigned long flags1;
295 unsigned long flags2;
296 unsigned long flags3;
297 unsigned long flags4;
299 local_irq_save_3(&flags1, &flags2, &flags3);
300 bpf_local_irq_restore(&flags3);
301 bpf_local_irq_save(&flags4);
302 bpf_local_irq_restore(&flags4);
303 bpf_local_irq_restore(&flags1);
308 __failure __msg("cannot restore irq state out of order")
309 int irq_restore_ooo_3_subprog(struct __sk_buff *ctx)
311 unsigned long flags1;
312 unsigned long flags2;
313 unsigned long flags3;
315 local_irq_save_3(&flags1, &flags2, &flags3);
316 bpf_local_irq_restore(&flags3);
317 bpf_local_irq_restore(&flags2);
318 bpf_local_irq_save(&flags3);
319 bpf_local_irq_restore(&flags1);
324 __failure __msg("expected an initialized")
325 int irq_restore_invalid(struct __sk_buff *ctx)
327 unsigned long flags1;
328 unsigned long flags = 0xfaceb00c;
330 bpf_local_irq_save(&flags1);
331 bpf_local_irq_restore(&flags);
336 __failure __msg("expected uninitialized")
337 int irq_save_invalid(struct __sk_buff *ctx)
339 unsigned long flags1;
341 bpf_local_irq_save(&flags1);
342 bpf_local_irq_save(&flags1);
347 __failure __msg("expected an initialized")
348 int irq_restore_iter(struct __sk_buff *ctx)
350 struct bpf_iter_num it;
352 bpf_iter_num_new(&it, 0, 42);
353 bpf_local_irq_restore((unsigned long *)&it);
358 __failure __msg("Unreleased reference id=1")
359 int irq_save_iter(struct __sk_buff *ctx)
361 struct bpf_iter_num it;
363 /* Ensure same sized slot has st->ref_obj_id set, so we reject based on
364 * slot_type != STACK_IRQ_FLAG...
366 _Static_assert(sizeof(it) == sizeof(unsigned long), "broken iterator size");
368 bpf_iter_num_new(&it, 0, 42);
369 bpf_local_irq_save((unsigned long *)&it);
370 bpf_local_irq_restore((unsigned long *)&it);
375 __failure __msg("expected an initialized")
376 int irq_flag_overwrite(struct __sk_buff *ctx)
380 bpf_local_irq_save(&flags);
382 bpf_local_irq_restore(&flags);
387 __failure __msg("expected an initialized")
388 int irq_flag_overwrite_partial(struct __sk_buff *ctx)
392 bpf_local_irq_save(&flags);
393 *(((char *)&flags) + 1) = 0xff;
394 bpf_local_irq_restore(&flags);
399 __failure __msg("cannot restore irq state out of order")
400 int irq_ooo_refs_array(struct __sk_buff *ctx)
402 unsigned long flags[4];
403 struct { int i; } *p;
406 bpf_local_irq_save(&flags[0]);
409 p = bpf_obj_new(typeof(*p));
411 bpf_local_irq_restore(&flags[0]);
416 bpf_local_irq_save(&flags[1]);
419 bpf_local_irq_save(&flags[2]);
421 /* Now when we remove ref=2, the verifier must not break the ordering in
422 * the refs array between 1,3,4. With an older implementation, the
423 * verifier would swap the last element with the removed element, but to
424 * maintain the stack property we need to use memmove.
428 /* Save and restore to reset active_irq_id to 3, as the ordering is now
429 * refs=1,4,3. When restoring the linear scan will find prev_id in order
432 bpf_local_irq_save(&flags[3]);
433 bpf_local_irq_restore(&flags[3]);
435 /* With the incorrect implementation, we can release flags[1], flags[2],
436 * and flags[0], i.e. in the wrong order.
438 bpf_local_irq_restore(&flags[1]);
439 bpf_local_irq_restore(&flags[2]);
440 bpf_local_irq_restore(&flags[0]);
444 char _license[] SEC("license") = "GPL";