Blame 0011-usb-check-page-select-value-while-processing-iTD.patch

7d975d
From: Prasad J Pandit <pjp@fedoraproject.org>
7d975d
Date: Wed, 20 Jan 2016 01:26:46 +0530
7d975d
Subject: [PATCH] usb: check page select value while processing iTD
7d975d
7d975d
While processing isochronous transfer descriptors(iTD), the page
7d975d
select(PG) field value could lead to an OOB read access. Add
7d975d
check to avoid it.
7d975d
7d975d
Reported-by: Qinghao Tang <luodalongde@gmail.com>
7d975d
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
7d975d
Message-id: 1453233406-12165-1-git-send-email-ppandit@redhat.com
7d975d
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
7d975d
(cherry picked from commit 49d925ce50383a286278143c05511d30ec41a36e)
7d975d
---
7d975d
 hw/usb/hcd-ehci.c | 10 ++++++----
7d975d
 1 file changed, 6 insertions(+), 4 deletions(-)
7d975d
7d975d
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
7d975d
index d07f228..c40013e 100644
7d975d
--- a/hw/usb/hcd-ehci.c
7d975d
+++ b/hw/usb/hcd-ehci.c
7d975d
@@ -1404,21 +1404,23 @@ static int ehci_process_itd(EHCIState *ehci,
7d975d
         if (itd->transact[i] & ITD_XACT_ACTIVE) {
7d975d
             pg   = get_field(itd->transact[i], ITD_XACT_PGSEL);
7d975d
             off  = itd->transact[i] & ITD_XACT_OFFSET_MASK;
7d975d
-            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
7d975d
-            ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK);
7d975d
             len  = get_field(itd->transact[i], ITD_XACT_LENGTH);
7d975d
 
7d975d
             if (len > max * mult) {
7d975d
                 len = max * mult;
7d975d
             }
7d975d
-
7d975d
-            if (len > BUFF_SIZE) {
7d975d
+            if (len > BUFF_SIZE || pg > 6) {
7d975d
                 return -1;
7d975d
             }
7d975d
 
7d975d
+            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
7d975d
             qemu_sglist_init(&ehci->isgl, ehci->device, 2, ehci->as);
7d975d
             if (off + len > 4096) {
7d975d
                 /* transfer crosses page border */
7d975d
+                if (pg == 6) {
7d975d
+                    return -1;  /* avoid page pg + 1 */
7d975d
+                }
7d975d
+                ptr2 = (itd->bufptr[pg + 1] & ITD_BUFPTR_MASK);
7d975d
                 uint32_t len2 = off + len - 4096;
7d975d
                 uint32_t len1 = len - len2;
7d975d
                 qemu_sglist_add(&ehci->isgl, ptr1 + off, len1);