qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PULL 3/5] ehci: fix fetch qtd race
Date: Fri, 14 Dec 2018 11:38:52 +0100	[thread overview]
Message-ID: <20181214103854.13820-4-kraxel@redhat.com> (raw)
In-Reply-To: <20181214103854.13820-1-kraxel@redhat.com>

The token field contains the (guest-filled) state of the qtd, which
indicates whenever the other fields are valid or not.  So make sure
we read the token first, otherwise we may end up with an stale next
pointer:

  (1) ehci reads next
  (2) guest writes next
  (3) guest writes token
  (4) ehci reads token
  (5) ehci operates with stale next.

Typical effect is that qemu doesn't notice that the guest appends new
qtds to the end of the queue.  Looks like the usb device stopped
responding.  Linux can recover from that, but leaves a message in the
kernel log that it did reset the usb device in question.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20181126100836.8805-1-kraxel@redhat.com
---
 hw/usb/hcd-ehci.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index e5acfc5ba5..8d44d483df 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1783,9 +1783,17 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
     EHCIqtd qtd;
     EHCIPacket *p;
     int again = 1;
+    uint32_t addr;
 
-    if (get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,
-                   sizeof(EHCIqtd) >> 2) < 0) {
+    addr = NLPTR_GET(q->qtdaddr);
+    if (get_dwords(q->ehci, addr +  8, &qtd.token,   1) < 0) {
+        return 0;
+    }
+    barrier();
+    if (get_dwords(q->ehci, addr +  0, &qtd.next,    1) < 0 ||
+        get_dwords(q->ehci, addr +  4, &qtd.altnext, 1) < 0 ||
+        get_dwords(q->ehci, addr + 12, qtd.bufptr,
+                   ARRAY_SIZE(qtd.bufptr)) < 0) {
         return 0;
     }
     ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
-- 
2.9.3

  parent reply	other threads:[~2018-12-14 10:39 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-14 10:38 [Qemu-devel] [PULL 0/5] Usb 20181214 patches Gerd Hoffmann
2018-12-14 10:38 ` [Qemu-devel] [PULL 1/5] pvusb: set max grants only in initialise Gerd Hoffmann
2018-12-14 10:38 ` [Qemu-devel] [PULL 2/5] usb-host: reset and close libusb_device_handle before qemu exit Gerd Hoffmann
2018-12-14 10:38 ` Gerd Hoffmann [this message]
2018-12-14 10:38 ` [Qemu-devel] [PULL 4/5] usb-mtp: use O_NOFOLLOW and O_CLOEXEC Gerd Hoffmann
2018-12-14 10:38 ` [Qemu-devel] [PULL 5/5] usb-mtp: Limit filename to object information size Gerd Hoffmann
2018-12-16 12:48 ` [Qemu-devel] [PULL 0/5] Usb 20181214 patches Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181214103854.13820-4-kraxel@redhat.com \
    --to=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).