~ruther/guix-local

7ef4119f0a4dcf32668f4f7f1ef730d35890a247 — Mark H Weaver 10 years ago bae8776
gnu: qemu: Add fixes for CVE-2015-5154 and CVE-2015-5158.

* gnu/packages/patches/qemu-CVE-2015-5154-pt1.patch,
  gnu/packages/patches/qemu-CVE-2015-5154-pt2.patch,
  gnu/packages/patches/qemu-CVE-2015-5154-pt3.patch,
  gnu/packages/patches/qemu-CVE-2015-5158.patch: New files.
* gnu-system.am (dist_patch_DATA): Add them.
* gnu/packages/qemu.scm (qemu-headless)[source]: Add patches.
M gnu-system.am => gnu-system.am +4 -0
@@ 603,6 603,10 @@ dist_patch_DATA =						\
  gnu/packages/patches/qemu-CVE-2015-4106-pt6.patch		\
  gnu/packages/patches/qemu-CVE-2015-4106-pt7.patch		\
  gnu/packages/patches/qemu-CVE-2015-4106-pt8.patch		\
  gnu/packages/patches/qemu-CVE-2015-5154-pt1.patch		\
  gnu/packages/patches/qemu-CVE-2015-5154-pt2.patch		\
  gnu/packages/patches/qemu-CVE-2015-5154-pt3.patch		\
  gnu/packages/patches/qemu-CVE-2015-5158.patch			\
  gnu/packages/patches/qt4-ldflags.patch			\
  gnu/packages/patches/qt4-tests.patch				\
  gnu/packages/patches/qt5-runpath.patch			\

A gnu/packages/patches/qemu-CVE-2015-5154-pt1.patch => gnu/packages/patches/qemu-CVE-2015-5154-pt1.patch +76 -0
@@ 0,0 1,76 @@
From a9de14175548c04e0f8be7fae219246509ba46a9 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 3 Jun 2015 14:13:31 +0200
Subject: [PATCH 1/3] ide: Check array bounds before writing to io_buffer
 (CVE-2015-5154)

If the end_transfer_func of a command is called because enough data has
been read or written for the current PIO transfer, and it fails to
correctly call the command completion functions, the DRQ bit in the
status register and s->end_transfer_func may remain set. This allows the
guest to access further bytes in s->io_buffer beyond s->data_end, and
eventually overflowing the io_buffer.

One case where this currently happens is emulation of the ATAPI command
START STOP UNIT.

This patch fixes the problem by adding explicit array bounds checks
before accessing the buffer instead of relying on end_transfer_func to
function correctly.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 122e955..44fcc23 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2021,6 +2021,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
     }
 
     p = s->data_ptr;
+    if (p + 2 > s->data_end) {
+        return;
+    }
+
     *(uint16_t *)p = le16_to_cpu(val);
     p += 2;
     s->data_ptr = p;
@@ -2042,6 +2046,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
     }
 
     p = s->data_ptr;
+    if (p + 2 > s->data_end) {
+        return 0;
+    }
+
     ret = cpu_to_le16(*(uint16_t *)p);
     p += 2;
     s->data_ptr = p;
@@ -2063,6 +2071,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
     }
 
     p = s->data_ptr;
+    if (p + 4 > s->data_end) {
+        return;
+    }
+
     *(uint32_t *)p = le32_to_cpu(val);
     p += 4;
     s->data_ptr = p;
@@ -2084,6 +2096,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
     }
 
     p = s->data_ptr;
+    if (p + 4 > s->data_end) {
+        return 0;
+    }
+
     ret = cpu_to_le32(*(uint32_t *)p);
     p += 4;
     s->data_ptr = p;
-- 
1.8.3.1

A gnu/packages/patches/qemu-CVE-2015-5154-pt2.patch => gnu/packages/patches/qemu-CVE-2015-5154-pt2.patch +28 -0
@@ 0,0 1,28 @@
From aa851d30acfbb9580098ac1dc82885530cb8b3c1 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 3 Jun 2015 14:17:46 +0200
Subject: [PATCH 2/3] ide/atapi: Fix START STOP UNIT command completion

The command must be completed on all code paths. START STOP UNIT with
pwrcnd set should succeed without doing anything.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/atapi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 950e311..79dd167 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -983,6 +983,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)

     if (pwrcnd) {
         /* eject/load only happens for power condition == 0 */
+        ide_atapi_cmd_ok(s);
         return;
     }

--
1.8.3.1


A gnu/packages/patches/qemu-CVE-2015-5154-pt3.patch => gnu/packages/patches/qemu-CVE-2015-5154-pt3.patch +71 -0
@@ 0,0 1,71 @@
From 1d3c2268f8708126a34064c2e0c1000b40e6f3e5 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 3 Jun 2015 14:41:27 +0200
Subject: [PATCH 3/3] ide: Clear DRQ after handling all expected accesses

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).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hw/ide/core.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 44fcc23..50449ca 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2028,8 +2028,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)
@@ -2053,8 +2055,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;
 }

@@ -2078,8 +2082,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)
@@ -2103,8 +2109,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;
 }

--
1.8.3.1


A gnu/packages/patches/qemu-CVE-2015-5158.patch => gnu/packages/patches/qemu-CVE-2015-5158.patch +45 -0
@@ 0,0 1,45 @@
c170aad8b057223b1139d72e5ce7acceafab4fa9
Author: Paolo Bonzini <pbonzini@redhat.com>
Date:   Tue Jul 21 08:59:39 2015 +0200

    scsi: fix buffer overflow in scsi_req_parse_cdb (CVE-2015-5158)
    
    This is a guest-triggerable buffer overflow present in QEMU 2.2.0
    and newer.  scsi_cdb_length returns -1 as an error value, but the
    caller does not check it.
    
    Luckily, the massive overflow means that QEMU will just SIGSEGV,
    making the impact much smaller.
    
    Reported-by: Zhu Donghai (朱东海) <donghai.zdh@alibaba-inc.com>
    Fixes: 1894df02811f6b79ea3ffbf1084599d96f316173
    Reviewed-by: Fam Zheng <famz@redhat.com>
    Cc: qemu-stable@nongnu.org
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

1 file changed, 6 insertions(+), 1 deletion(-)
 hw/scsi/scsi-bus.c | 7 ++++++-

	Modified   hw/scsi/scsi-bus.c
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index f50b2f0..f0ae462 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1239,10 +1239,15 @@ int scsi_cdb_length(uint8_t *buf) {
 int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
 {
     int rc;
+    int len;
 
     cmd->lba = -1;
-    cmd->len = scsi_cdb_length(buf);
+    len = scsi_cdb_length(buf);
+    if (len < 0) {
+        return -1;
+    }
 
+    cmd->len = len;
     switch (dev->type) {
     case TYPE_TAPE:
         rc = scsi_req_stream_xfer(cmd, dev, buf);


M gnu/packages/qemu.scm => gnu/packages/qemu.scm +5 -1
@@ 65,7 65,11 @@
                                          "qemu-CVE-2015-4106-pt5.patch"
                                          "qemu-CVE-2015-4106-pt6.patch"
                                          "qemu-CVE-2015-4106-pt7.patch"
                                          "qemu-CVE-2015-4106-pt8.patch")))))
                                          "qemu-CVE-2015-4106-pt8.patch"
                                          "qemu-CVE-2015-5154-pt1.patch"
                                          "qemu-CVE-2015-5154-pt2.patch"
                                          "qemu-CVE-2015-5154-pt3.patch"
                                          "qemu-CVE-2015-5158.patch")))))
    (build-system gnu-build-system)
    (arguments
     '(#:phases (alist-replace