]> xenbits.xensource.com Git - qemu-upstream-unstable.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:35:25 +0000 (15:35 +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 a4467e91fc33ea1c1604cbf6ee92ac0273bc6002..1d64bcac6c2ab31117a3ec03849736b7518070a8 100644 (file)
@@ -2020,8 +2020,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)
@@ -2045,8 +2047,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;
 }
 
@@ -2070,8 +2074,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)
@@ -2095,8 +2101,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;
 }