]> xenbits.xensource.com Git - qemu-xen.git/commitdiff
ide: Clear DRQ after handling all expected accesses (CVE-2015-5154)
authorKevin Wolf <kwolf@redhat.com>
Mon, 27 Jul 2015 03:42:53 +0000 (23:42 -0400)
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>
Wed, 29 Jul 2015 15:50:05 +0000 (15:50 +0000)
This is additional hardening against an end_transfer_func that fails to
clear the DRQ status bit. The bit must be unset as soon as the PIO
transfer has completed, so it's better to do this in a central place
instead of duplicating the code in all commands (and forgetting it in
some).

upstream-commit-id: cb72cba83021fa42719e73a5249c12096a4d1cfc

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
hw/ide/core.c

index 44bbef22b450ca7848ebb3d2e1dd22401dc7a2d7..9ccd50a35af3159cdfd8ecfa38723dd46306c22b 100644 (file)
@@ -1751,8 +1751,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
     *(uint16_t *)p = le16_to_cpu(val);
     p += 2;
     s->data_ptr = p;
-    if (p >= s->data_end)
+    if (p >= s->data_end) {
+        s->status &= ~DRQ_STAT;
         s->end_transfer_func(s);
+    }
 }
 
 uint32_t ide_data_readw(void *opaque, uint32_t addr)
@@ -1776,8 +1778,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
     ret = cpu_to_le16(*(uint16_t *)p);
     p += 2;
     s->data_ptr = p;
-    if (p >= s->data_end)
+    if (p >= s->data_end) {
+        s->status &= ~DRQ_STAT;
         s->end_transfer_func(s);
+    }
     return ret;
 }
 
@@ -1801,8 +1805,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
     *(uint32_t *)p = le32_to_cpu(val);
     p += 4;
     s->data_ptr = p;
-    if (p >= s->data_end)
+    if (p >= s->data_end) {
+        s->status &= ~DRQ_STAT;
         s->end_transfer_func(s);
+    }
 }
 
 uint32_t ide_data_readl(void *opaque, uint32_t addr)
@@ -1826,8 +1832,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
     ret = cpu_to_le32(*(uint32_t *)p);
     p += 4;
     s->data_ptr = p;
-    if (p >= s->data_end)
+    if (p >= s->data_end) {
+        s->status &= ~DRQ_STAT;
         s->end_transfer_func(s);
+    }
     return ret;
 }