diff options
| author | Amery Hung <ameryhung@gmail.com> | 2026-09-11 15:04:14 -0700 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-09-11 20:16:05 -0700 |
| commit | 4f18de58a44cc15e2ec18c07bb1897d97f9dc1a8 (patch) | |
| tree | 82f539669161c193ea6c519b820c95b95aff24cf /tools/testing/selftests/bpf | |
| parent | 5dc1549afac9c5d82bdde9ac4e000c859bbbf991 (diff) | |
| download | linux-next-4f18de58a44cc15e2ec18c07bb1897d97f9dc1a8.tar.gz linux-next-4f18de58a44cc15e2ec18c07bb1897d97f9dc1a8.zip | |
selftests/bpf: Test nullable per-CPU kptr identity after exchange
Pass two unchecked bpf_percpu_obj_new() results to bpf_kptr_xchg()
inside an RCU critical section. The exchanges consume ownership and
leave nullable RCU-protected aliases.
Checking the first alias must not make the second non-NULL. Verify that
bpf_this_cpu_ptr() still rejects the unchecked second alias.
Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/r/20260911220415.1396439-23-ameryhung@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/testing/selftests/bpf')
| -rw-r--r-- | tools/testing/selftests/bpf/progs/percpu_alloc_fail.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/percpu_alloc_fail.c b/tools/testing/selftests/bpf/progs/percpu_alloc_fail.c index 3701f4ea58c7..57615b0f0c25 100644 --- a/tools/testing/selftests/bpf/progs/percpu_alloc_fail.c +++ b/tools/testing/selftests/bpf/progs/percpu_alloc_fail.c @@ -24,6 +24,7 @@ struct val_600b_t { struct elem { long sum; struct val_t __percpu_kptr *pc; + struct val_t __percpu_kptr *pc2; }; struct { @@ -46,6 +47,8 @@ struct { struct task_struct *bpf_task_from_pid(s32 pid) __ksym; void bpf_task_release(struct task_struct *p) __ksym; +void bpf_rcu_read_lock(void) __ksym; +void bpf_rcu_read_unlock(void) __ksym; long ret; @@ -124,6 +127,38 @@ int BPF_PROG(test_array_map_3) } SEC("?fentry.s/bpf_fentry_test1") +__failure __msg("Possibly NULL pointer passed to trusted R1") +int BPF_PROG(reject_nullable_percpu_xchg_alias) +{ + struct val_t __percpu_kptr *p1, *p2, *old; + struct val_t *v; + struct elem *e; + int index = 0; + + e = bpf_map_lookup_elem(&array, &index); + if (!e) + return 0; + + p1 = bpf_percpu_obj_new(struct val_t); + p2 = bpf_percpu_obj_new(struct val_t); + + bpf_rcu_read_lock(); + old = bpf_kptr_xchg(&e->pc, p1); + if (old) + bpf_percpu_obj_drop(old); + old = bpf_kptr_xchg(&e->pc2, p2); + if (old) + bpf_percpu_obj_drop(old); + + if (p1) { + v = bpf_this_cpu_ptr(p2); + v->b = 1; + } + bpf_rcu_read_unlock(); + return 0; +} + +SEC("?fentry.s/bpf_fentry_test1") __failure __msg("R1 expected for bpf_percpu_obj_drop()") int BPF_PROG(test_array_map_4) { |
