Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vhost_net: fix sleeping with preempt-disabled in vhost_net_busy_poll()

syzbot reported "sleeping function called from invalid context" in
vhost_net_busy_poll().

Commit 030881372460 ("vhost_net: basic polling support") introduced a
busy-poll loop and preempt_{disable,enable}() around it, where each
iteration calls a sleepable function inside the loop.

The purpose of disabling preemption was to keep local_clock()-based
timeout accounting on a single CPU, rather than as a requirement of
busy-poll itself:

https://lore.kernel.org/1448435489-5949-4-git-send-email-jasowang@redhat.com

From this perspective, migrate_disable() is sufficient here, so replace
preempt_disable() with migrate_disable(), avoiding sleepable accesses
from a preempt-disabled context.

Fixes: 030881372460 ("vhost_net: basic polling support")
Tested-by: syzbot+6985cb8e543ea90ba8ee@syzkaller.appspotmail.com
Reported-by: syzbot+6985cb8e543ea90ba8ee@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/69e6a414.050a0220.24bfd3.002d.GAE@google.com/T/
Signed-off-by: Kohei Enju <kohei@enjuk.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kohei Enju and committed by
Jakub Kicinski
e08a9fac 076b8cad

+2 -2
+2 -2
drivers/vhost/net.c
··· 560 560 busyloop_timeout = poll_rx ? rvq->busyloop_timeout: 561 561 tvq->busyloop_timeout; 562 562 563 - preempt_disable(); 563 + migrate_disable(); 564 564 endtime = busy_clock() + busyloop_timeout; 565 565 566 566 while (vhost_can_busy_poll(endtime)) { ··· 577 577 cpu_relax(); 578 578 } 579 579 580 - preempt_enable(); 580 + migrate_enable(); 581 581 582 582 if (poll_rx || sock_has_rx_data(sock)) 583 583 vhost_net_busy_poll_try_queue(net, vq);