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

a13b82
From 892bb2a720de57109f7e8526879069abcaab38bf 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)
a13b82
Bugzilla: 1243689
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
a13b82
index 24a1708..ada26c0 100644
a13b82
--- a/hw/ide/core.c
a13b82
+++ b/hw/ide/core.c
a13b82
@@ -1849,6 +1849,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;
a13b82
@@ -1870,6 +1874,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;
a13b82
@@ -1891,6 +1899,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;
a13b82
@@ -1912,6 +1924,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