Skip to content

Commit a1e5c46

Browse files
theihorAlexei Starovoitov
authored andcommitted
selftests/bpf: Add tests for bpf_throw lock leak from subprogs
Add test cases to ensure the verifier correctly rejects bpf_throw from subprogs when RCU, preempt, or IRQ locks are held: * reject_subprog_rcu_lock_throw: subprog acquires bpf_rcu_read_lock and then calls bpf_throw * reject_subprog_throw_preempt_lock: always-throwing subprog called while caller holds bpf_preempt_disable * reject_subprog_throw_irq_lock: always-throwing subprog called while caller holds bpf_local_irq_save Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Ihor Solodrai <[email protected]> Acked-by: Yonghong Song <[email protected]> Acked-by: Kumar Kartikeya Dwivedi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 6c21285 commit a1e5c46

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

tools/testing/selftests/bpf/progs/exceptions_fail.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010
extern void bpf_rcu_read_lock(void) __ksym;
1111
extern void bpf_rcu_read_unlock(void) __ksym;
12+
extern void bpf_preempt_disable(void) __ksym;
13+
extern void bpf_preempt_enable(void) __ksym;
14+
extern void bpf_local_irq_save(unsigned long *) __ksym;
15+
extern void bpf_local_irq_restore(unsigned long *) __ksym;
1216

1317
#define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
1418

@@ -349,4 +353,47 @@ int reject_exception_throw_cb_diff(struct __sk_buff *ctx)
349353
return 0;
350354
}
351355

356+
__noinline static int always_throws(void)
357+
{
358+
bpf_throw(0);
359+
return 0;
360+
}
361+
362+
__noinline static int rcu_lock_then_throw(void)
363+
{
364+
bpf_rcu_read_lock();
365+
bpf_throw(0);
366+
return 0;
367+
}
368+
369+
SEC("?tc")
370+
__failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region")
371+
int reject_subprog_rcu_lock_throw(void *ctx)
372+
{
373+
rcu_lock_then_throw();
374+
return 0;
375+
}
376+
377+
SEC("?tc")
378+
__failure __msg("bpf_throw cannot be used inside bpf_preempt_disable-ed region")
379+
int reject_subprog_throw_preempt_lock(void *ctx)
380+
{
381+
bpf_preempt_disable();
382+
always_throws();
383+
bpf_preempt_enable();
384+
return 0;
385+
}
386+
387+
SEC("?tc")
388+
__failure __msg("bpf_throw cannot be used inside bpf_local_irq_save-ed region")
389+
int reject_subprog_throw_irq_lock(void *ctx)
390+
{
391+
unsigned long flags;
392+
393+
bpf_local_irq_save(&flags);
394+
always_throws();
395+
bpf_local_irq_restore(&flags);
396+
return 0;
397+
}
398+
352399
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)