summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNing Ding <dingning04@gmail.com>2026-09-04 10:43:21 +0200
committerAlexei Starovoitov <ast@kernel.org>2026-09-04 07:58:36 -0700
commit9492baf8532ca285c58b82a269acd7a57e205ae9 (patch)
treeec8406fa98b9cc67556f8bfd4f637a2612600ec9
parent7441ee8276641bddaf1cba7bb75ef9c1458ceb3b (diff)
downloadlinux-9492baf8532ca285c58b82a269acd7a57e205ae9.tar.gz
linux-9492baf8532ca285c58b82a269acd7a57e205ae9.zip
selftests/bpf: Reject refcount acquisition after RCU unlock
Add a sleepable verifier test that loads a refcount-only local kptr in an explicit RCU read-side critical section, ends the section, and passes the pointer to bpf_refcount_acquire(). The loaded pointer never carries NON_OWN_REF. After RCU unlock it retains MEM_ALLOC while becoming PTR_UNTRUSTED, which previously made the kfunc argument check accept it as a live allocated object. Expect verification to reject the untrusted argument instead. Signed-off-by: Ning Ding <dingning04@gmail.com> [ kkd: Rewrote commit log ] Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20260904084325.52250-9-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r--tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
index f787ecf189d8..338e43822ffe 100644
--- a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
+++ b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c
@@ -190,6 +190,33 @@ long rbtree_remove_after_rcu_unlock(void *ctx)
}
SEC("?syscall")
+__failure __msg("R1 is neither owning or non-owning ref")
+long refcount_acquire_after_rcu_unlock(void *ctx)
+{
+ struct map_value_refcount_only *mapval;
+ struct node_refcount_only *node, *ref;
+ int idx = 0;
+
+ mapval = bpf_map_lookup_elem(&stashed_refcount_only, &idx);
+ if (!mapval)
+ return 0;
+
+ bpf_rcu_read_lock();
+ node = mapval->node;
+ if (!node) {
+ bpf_rcu_read_unlock();
+ return 0;
+ }
+ bpf_rcu_read_unlock();
+
+ ref = bpf_refcount_acquire(node);
+ if (ref)
+ bpf_obj_drop(ref);
+
+ return 0;
+}
+
+SEC("?syscall")
__failure __msg("invalid mem access 'scalar'")
long graph_kptr_after_spin_unlock(void *ctx)
{