From 49d925ce50383a286278143c05511d30ec41a36e Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Wed, 20 Jan 2016 01:26:46 +0530 Subject: [PATCH 1/2] usb: check page select value while processing iTD While processing isochronous transfer descriptors(iTD), the page select(PG) field value could lead to an OOB read access. Add check to avoid it. Reported-by: Qinghao Tang Signed-off-by: Prasad J Pandit Message-id: 1453233406-12165-1-git-send-email-ppandit@redhat.com Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index ab002680c7..93601d9627 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1405,21 +1405,23 @@ static int ehci_process_itd(EHCIState *ehci, if (itd->transact[i] & ITD_XACT_ACTIVE) { pg = get_field(itd->transact[i], ITD_XACT_PGSEL); off = itd->transact[i] & ITD_XACT_OFFSET_MASK; - ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK); - ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK); len = get_field(itd->transact[i], ITD_XACT_LENGTH); if (len > max * mult) { len = max * mult; } - - if (len > BUFF_SIZE) { + if (len > BUFF_SIZE || pg > 6) { return -1; } + ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK); qemu_sglist_init(&ehci->isgl, ehci->device, 2, ehci->as); if (off + len > 4096) { /* transfer crosses page border */ + if (pg == 6) { + return -1; /* avoid page pg + 1 */ + } + ptr2 = (itd->bufptr[pg + 1] & ITD_BUFPTR_MASK); uint32_t len2 = off + len - 4096; uint32_t len1 = len - len2; qemu_sglist_add(&ehci->isgl, ptr1 + off, len1); From 5a8660741a8aa19fbf8a5e8a2b3aac88664f4e66 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 19 Jan 2016 12:44:44 +0100 Subject: [PATCH 2/2] ehci: update irq on reset After clearing the status register we also have to update the irq line status. Otherwise a irq which happends to be pending at reset time causes a interrupt storm. And the guest can't stop as the status register doesn't indicate any pending interrupt. Both NetBSD and FreeBSD hang on shutdown because of that. Cc: qemu-stable@nongnu.org Reported-by: Andrey Korolyov Signed-off-by: Gerd Hoffmann Message-id: 1453203884-4125-1-git-send-email-kraxel@redhat.com --- hw/usb/hcd-ehci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 93601d9627..1b50601fc1 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -866,6 +866,7 @@ void ehci_reset(void *opaque) s->usbsts = USBSTS_HALT; s->usbsts_pending = 0; s->usbsts_frindex = 0; + ehci_update_irq(s); s->astate = EST_INACTIVE; s->pstate = EST_INACTIVE;