Skip to content

Commit a439184

Browse files
fomichevborkmann
authored andcommitted
bpf/test_run: fix unkillable BPF_PROG_TEST_RUN for flow dissector
Syzbot found out that running BPF_PROG_TEST_RUN with repeat=0xffffffff makes process unkillable. The problem is that when CONFIG_PREEMPT is enabled, we never see need_resched() return true. This is due to the fact that preempt_enable() (which we do in bpf_test_run_one on each iteration) now handles resched if it's needed. Let's disable preemption for the whole run, not per test. In this case we can properly see whether resched is needed. Let's also properly return -EINTR to the userspace in case of a signal interrupt. This is a follow up for a recently fixed issue in bpf_test_run, see commit df1a2cb ("bpf/test_run: fix unkillable BPF_PROG_TEST_RUN"). Reported-by: syzbot <syzkaller@googlegroups.com> Signed-off-by: Stanislav Fomichev <sdf@google.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
1 parent fd92d66 commit a439184

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

net/bpf/test_run.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,31 +293,45 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
293293
if (!repeat)
294294
repeat = 1;
295295

296+
rcu_read_lock();
297+
preempt_disable();
296298
time_start = ktime_get_ns();
297299
for (i = 0; i < repeat; i++) {
298-
preempt_disable();
299-
rcu_read_lock();
300300
retval = __skb_flow_bpf_dissect(prog, skb,
301301
&flow_keys_dissector,
302302
&flow_keys);
303-
rcu_read_unlock();
304-
preempt_enable();
303+
304+
if (signal_pending(current)) {
305+
preempt_enable();
306+
rcu_read_unlock();
307+
308+
ret = -EINTR;
309+
goto out;
310+
}
305311

306312
if (need_resched()) {
307-
if (signal_pending(current))
308-
break;
309313
time_spent += ktime_get_ns() - time_start;
314+
preempt_enable();
315+
rcu_read_unlock();
316+
310317
cond_resched();
318+
319+
rcu_read_lock();
320+
preempt_disable();
311321
time_start = ktime_get_ns();
312322
}
313323
}
314324
time_spent += ktime_get_ns() - time_start;
325+
preempt_enable();
326+
rcu_read_unlock();
327+
315328
do_div(time_spent, repeat);
316329
duration = time_spent > U32_MAX ? U32_MAX : (u32)time_spent;
317330

318331
ret = bpf_test_finish(kattr, uattr, &flow_keys, sizeof(flow_keys),
319332
retval, duration);
320333

334+
out:
321335
kfree_skb(skb);
322336
kfree(sk);
323337
return ret;

0 commit comments

Comments
 (0)