From 11381e795844e50818cb8b1fa05244d03fe5e0c6 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Thu, 21 Aug 2014 12:05:40 -0500 Subject: [CHANGE 2/3] usb: Avoid reentrancy of ehci_advance_async_state (downstream only) To: rhvirt-patches@redhat.com, jen@redhat.com RH-Author: Fam Zheng Message-id: <1408622740-10835-3-git-send-email-famz@redhat.com> Patchwork-id: 60662 O-Subject: [RHEL-6.6 qemu-kvm PATCH v4 2/2] usb: Avoid reentrancy of ehci_advance_async_state (downstream only) Bugzilla: 1018537 RH-Acked-by: Markus Armbruster RH-Acked-by: Kevin Wolf RH-Acked-by: Stefan Hajnoczi ehci_advance_async_state can be called either by the ehci->frame_timer or by ehci->async_bh. It's possible that during one main loop iteration, ehci->async_bh is scheduled by a USB command, then ehci->frame_timer is fired. In this case ehci_advance_async_state is called twice by main loop in a row. Another case is that ehci_advance_async_state triggers io_cancel code, which calls qemu_aio_wait() then qemu_bh_poll(). Then, ehci_advance_async_state reenters itself! This will cause unexpected results such as assertion failure in usb_msd_cancel_io(), because ehci_advance_async_state is not reentrant safe. We can avoid this by simply cancelling the BH when entering ehci_advance_async_state. Upstream has very different ehci async code so it will not hit this issue. Signed-off-by: Fam Zheng --- hw/usb-ehci.c | 1 + 1 file changed, 1 insertion(+) Signed-off-by: Jeff E. Nelson --- hw/usb-ehci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 9aaccf5..baf4084 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -2034,6 +2034,7 @@ static void ehci_advance_async_state(EHCIState *ehci) { const int async = 1; + qemu_bh_cancel(ehci->async_bh); switch(ehci_get_state(ehci, async)) { case EST_INACTIVE: if (!(ehci->usbcmd & USBCMD_ASE)) { -- 1.9.3