summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/bpf
diff options
context:
space:
mode:
authorAmery Hung <ameryhung@gmail.com>2026-09-11 15:04:14 -0700
committerAlexei Starovoitov <ast@kernel.org>2026-09-11 20:16:05 -0700
commit4f18de58a44cc15e2ec18c07bb1897d97f9dc1a8 (patch)
tree82f539669161c193ea6c519b820c95b95aff24cf /tools/testing/selftests/bpf
parent5dc1549afac9c5d82bdde9ac4e000c859bbbf991 (diff)
downloadlinux-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.c35
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)
{