From e5e5a00223bf27197abc604e81cde3dc85600a28 Mon Sep 17 00:00:00 2001 From: Sahil Chandna Date: Sun, 9 Nov 2025 23:06:48 +0530 Subject: [PATCH] bpf: use preempt_disable/enable() to protect bpf_bprintf_buffers nesting The bpf_bprintf_prepare() and related helpers (bpf_try_get_buffers() / bpf_put_buffers()) rely on a per-CPU counter bpf_bprintf_nest_level to manage nested buffer usage. However, when invoked from different contexts (process, softirq, NMI), the nesting counter can become inconsistent if task migration occurs between CPUs during these operations. This can result in warnings such as: WARNING: CPU: 1 PID: 6145 at kernel/bpf/helpers.c:781 bpf_try_get_buffers kernel/bpf/helpers.c:781 [inline] WARNING: CPU: 1 PID: 6145 at kernel/bpf/helpers.c:781 bpf_bprintf_prepare+0x12cf/0x13a0 kernel/bpf/helpers.c:834 Having only migrate_disable is insufficient here to prevent nesting, hence add preempt_disable()/enable() around buffer acquisition and release. Reported-by: syzbot+b0cff308140f79a9c4cb@syzkaller.appspotmail.comi Closes: https://syzkaller.appspot.com/bug?extid=b0cff308140f79a9c4cb Fixes: 7c33e97a6ef5 ("bpf: Do not disable preemption in bpf_test_run().") Suggested-by: Yonghong Song Signed-off-by: Sahil Chandna --- kernel/bpf/helpers.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 865b0dae38d12..99780b654e8c3 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -774,9 +774,11 @@ int bpf_try_get_buffers(struct bpf_bprintf_buffers **bufs) { int nest_level; + preempt_disable(); nest_level = this_cpu_inc_return(bpf_bprintf_nest_level); if (WARN_ON_ONCE(nest_level > MAX_BPRINTF_NEST_LEVEL)) { this_cpu_dec(bpf_bprintf_nest_level); + preempt_enable(); return -EBUSY; } *bufs = this_cpu_ptr(&bpf_bprintf_bufs[nest_level - 1]); @@ -786,9 +788,12 @@ int bpf_try_get_buffers(struct bpf_bprintf_buffers **bufs) void bpf_put_buffers(void) { - if (WARN_ON_ONCE(this_cpu_read(bpf_bprintf_nest_level) == 0)) + if (WARN_ON_ONCE(this_cpu_read(bpf_bprintf_nest_level) == 0)) { + preempt_enable(); return; + } this_cpu_dec(bpf_bprintf_nest_level); + preempt_enable(); } void bpf_bprintf_cleanup(struct bpf_bprintf_data *data)