[PATCH bpf] bpf: Hash lock addresses in rqspinlock violation reports

From: Aohan Mei

Date: Tue Sep 01 2026 - 00:22:10 EST


From: Aohan Mei <henrymei@xxxxxxxxxxx>

bpf_prog_report_rqspinlock_violation() prints the attempted lock and
every held lock with %px, which expands to the raw pointer value.
The report lands in the program's BPF_STDERR stream, and that stream
is readable through BPF_PROG_STREAM_READ_BY_FD with no privilege
check on the read side: prog_stream_read() only validates the fd
with bpf_prog_get().

Any user with read access to the program fd (a shared fd, a BPF
token delegation, or an unprivileged child) can therefore read back
the raw kernel addresses of the rqspinlock objects, which are
dynamic allocations whose placement depends on KASLR and the slab
layout. The verifier-facing log path gates pointer printing on
allow_ptr_leaks; the stream path has no equivalent gate.

Print the ptr_to_hashval() hash of each address instead, so the
report still allows correlating the attempted lock with the held
locks within a boot, without exposing the raw addresses. Fall back
to printing 0 if hashing fails.

Fixes: ecec5b5743bf ("bpf: Report rqspinlock deadlocks/timeout to BPF stderr")
Reported-by: TencentOS Corvus AI <corvus@xxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: CodeBuddy:Kimi-K3
Signed-off-by: Aohan Mei <henrymei@xxxxxxxxxxx>
---
kernel/bpf/rqspinlock.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c
index 111ec80ea958..5721dc1a9577 100644
--- a/kernel/bpf/rqspinlock.c
+++ b/kernel/bpf/rqspinlock.c
@@ -16,6 +16,7 @@
#include <linux/smp.h>
#include <linux/bug.h>
#include <linux/bpf.h>
+#include <linux/string.h>
#include <linux/err.h>
#include <linux/cpumask.h>
#include <linux/percpu.h>
@@ -673,6 +674,7 @@ __bpf_kfunc_start_defs();
static void bpf_prog_report_rqspinlock_violation(const char *str, void *lock, bool irqsave)
{
struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+ unsigned long hashval;
struct bpf_stream_stage ss;
struct bpf_prog *prog;

@@ -681,10 +683,15 @@ static void bpf_prog_report_rqspinlock_violation(const char *str, void *lock, bo
return;
bpf_stream_stage(ss, prog, BPF_STDERR, ({
bpf_stream_printk(ss, "ERROR: %s for bpf_res_spin_lock%s\n", str, irqsave ? "_irqsave" : "");
- bpf_stream_printk(ss, "Attempted lock = 0x%px\n", lock);
+ if (ptr_to_hashval(lock, &hashval))
+ hashval = 0;
+ bpf_stream_printk(ss, "Attempted lock = 0x%08lx\n", hashval);
bpf_stream_printk(ss, "Total held locks = %d\n", rqh->cnt);
- for (int i = 0; i < min(RES_NR_HELD, rqh->cnt); i++)
- bpf_stream_printk(ss, "Held lock[%2d] = 0x%px\n", i, rqh->locks[i]);
+ for (int i = 0; i < min(RES_NR_HELD, rqh->cnt); i++) {
+ if (ptr_to_hashval(rqh->locks[i], &hashval))
+ hashval = 0;
+ bpf_stream_printk(ss, "Held lock[%2d] = 0x%08lx\n", i, hashval);
+ }
bpf_stream_dump_stack(ss);
}));
}
--
2.43.7