mirror of https://github.com/torvalds/linux.git
bpf: Prevent nesting overflow in bpf_try_get_buffers
bpf_try_get_buffers() returns one of multiple per-CPU buffers based on a
per-CPU nesting counter. This mechanism expects that buffers are not
endlessly acquired before being returned. migrate_disable() ensures that a
task remains on the same CPU, but it does not prevent the task from being
preempted by another task on that CPU.
Without disabled preemption, a task may be preempted while holding a
buffer, allowing another task to run on same CPU and acquire an
additional buffer. Several such preemptions can cause the per-CPU
nest counter to exceed MAX_BPRINTF_NEST_LEVEL and trigger the warning in
bpf_try_get_buffers(). Adding preempt_disable()/preempt_enable() around
buffer acquisition and release prevents this task preemption and
preserves the intended bounded nesting behavior.
Reported-by: syzbot+b0cff308140f79a9c4cb@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/68f6a4c8.050a0220.1be48.0011.GAE@google.com/
Fixes: 4223bf833c ("bpf: Remove preempt_disable in bpf_try_get_buffers")
Suggested-by: Yonghong Song <yonghong.song@linux.dev>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Sahil Chandna <chandna.sahil@gmail.com>
Link: https://lore.kernel.org/r/20251114064922.11650-1-chandna.sahil@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
93ce3bee31
commit
c1da3df719
|
|
@ -774,9 +774,11 @@ int bpf_try_get_buffers(struct bpf_bprintf_buffers **bufs)
|
||||||
{
|
{
|
||||||
int nest_level;
|
int nest_level;
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
nest_level = this_cpu_inc_return(bpf_bprintf_nest_level);
|
nest_level = this_cpu_inc_return(bpf_bprintf_nest_level);
|
||||||
if (WARN_ON_ONCE(nest_level > MAX_BPRINTF_NEST_LEVEL)) {
|
if (WARN_ON_ONCE(nest_level > MAX_BPRINTF_NEST_LEVEL)) {
|
||||||
this_cpu_dec(bpf_bprintf_nest_level);
|
this_cpu_dec(bpf_bprintf_nest_level);
|
||||||
|
preempt_enable();
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
*bufs = this_cpu_ptr(&bpf_bprintf_bufs[nest_level - 1]);
|
*bufs = this_cpu_ptr(&bpf_bprintf_bufs[nest_level - 1]);
|
||||||
|
|
@ -789,6 +791,7 @@ 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))
|
||||||
return;
|
return;
|
||||||
this_cpu_dec(bpf_bprintf_nest_level);
|
this_cpu_dec(bpf_bprintf_nest_level);
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpf_bprintf_cleanup(struct bpf_bprintf_data *data)
|
void bpf_bprintf_cleanup(struct bpf_bprintf_data *data)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue