Blame SOURCES/kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch

05bba0
From 03f2b3e5198471d80c3740450113643dff2109ce Mon Sep 17 00:00:00 2001
a13b82
From: Kevin Wolf <kwolf@redhat.com>
a13b82
Date: Thu, 16 Jul 2015 16:15:58 +0200
a13b82
Subject: [PATCH 1/3] ide: Check array bounds before writing to io_buffer
a13b82
 (CVE-2015-5154)
a13b82
a13b82
Message-id: <1437056160-3284-2-git-send-email-kwolf@redhat.com>
a13b82
Patchwork-id: n/a
a13b82
O-Subject: [virt-devel] [RHEL/RHEV-7 qemu-kvm(-rhev) EMBARGOED PATCH 1/3] ide:
a13b82
        Check array bounds before writing to io_buffer (CVE-2015-5154)
05bba0
Bugzilla: 1243690
a13b82
RH-Acked-by: Petr Matousek <pmatouse@redhat.com>
a13b82
RH-Acked-by: John Snow <jsnow@redhat.com>
a13b82
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
a13b82
a13b82
If the end_transfer_func of a command is called because enough data has
a13b82
been read or written for the current PIO transfer, and it fails to
a13b82
correctly call the command completion functions, the DRQ bit in the
a13b82
status register and s->end_transfer_func may remain set. This allows the
a13b82
guest to access further bytes in s->io_buffer beyond s->data_end, and
a13b82
eventually overflowing the io_buffer.
a13b82
a13b82
One case where this currently happens is emulation of the ATAPI command
a13b82
START STOP UNIT.
a13b82
a13b82
This patch fixes the problem by adding explicit array bounds checks
a13b82
before accessing the buffer instead of relying on end_transfer_func to
a13b82
function correctly.
a13b82
a13b82
Cc: qemu-stable@nongnu.org
a13b82
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
a13b82
---
a13b82
 hw/ide/core.c | 16 ++++++++++++++++
a13b82
 1 file changed, 16 insertions(+)
a13b82
a13b82
diff --git a/hw/ide/core.c b/hw/ide/core.c
05bba0
index d9fdb03..29bda6b 100644
a13b82
--- a/hw/ide/core.c
a13b82
+++ b/hw/ide/core.c
05bba0
@@ -1850,6 +1850,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
a13b82
     }
a13b82
 
a13b82
     p = s->data_ptr;
a13b82
+    if (p + 2 > s->data_end) {
a13b82
+        return;
a13b82
+    }
a13b82
+
a13b82
     *(uint16_t *)p = le16_to_cpu(val);
a13b82
     p += 2;
a13b82
     s->data_ptr = p;
05bba0
@@ -1871,6 +1875,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
a13b82
     }
a13b82
 
a13b82
     p = s->data_ptr;
a13b82
+    if (p + 2 > s->data_end) {
a13b82
+        return 0;
a13b82
+    }
a13b82
+
a13b82
     ret = cpu_to_le16(*(uint16_t *)p);
a13b82
     p += 2;
a13b82
     s->data_ptr = p;
05bba0
@@ -1892,6 +1900,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
a13b82
     }
a13b82
 
a13b82
     p = s->data_ptr;
a13b82
+    if (p + 4 > s->data_end) {
a13b82
+        return;
a13b82
+    }
a13b82
+
a13b82
     *(uint32_t *)p = le32_to_cpu(val);
a13b82
     p += 4;
a13b82
     s->data_ptr = p;
05bba0
@@ -1913,6 +1925,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
a13b82
     }
a13b82
 
a13b82
     p = s->data_ptr;
a13b82
+    if (p + 4 > s->data_end) {
a13b82
+        return 0;
a13b82
+    }
a13b82
+
a13b82
     ret = cpu_to_le32(*(uint32_t *)p);
a13b82
     p += 4;
a13b82
     s->data_ptr = p;
a13b82
-- 
a13b82
1.8.3.1
a13b82