crobinso pushed to qemu (f21). "Qemu: PRDT overflow from guest to host (bz #1204919, bz #1205322) (..more)"

notifications at fedoraproject.org notifications at fedoraproject.org
Fri Mar 27 18:41:17 UTC 2015


>From 29e31e320f42ace6782d16ddf552d3540b28a9c3 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso at redhat.com>
Date: Fri, 27 Mar 2015 14:40:27 -0400
Subject: Qemu: PRDT overflow from guest to host (bz #1204919, bz #1205322)
 CVE-2014-8106: cirrus: insufficient blit region checks (bz #1170612, bz
 #1169454) Fix .vdi disk corruption (bz #1199400) Don't install ksm services
 as executable (bz #1192720)


diff --git a/0002-aarch64-Allow-kernel-option-to-take-a-gzip-compresse.patch b/0002-aarch64-Allow-kernel-option-to-take-a-gzip-compresse.patch
index 637fa3c..4dfed3f 100644
--- a/0002-aarch64-Allow-kernel-option-to-take-a-gzip-compresse.patch
+++ b/0002-aarch64-Allow-kernel-option-to-take-a-gzip-compresse.patch
@@ -1,7 +1,6 @@
-From e96a3d72b1f869ee3bf0bdbb4a3ca8f9ae4de144 Mon Sep 17 00:00:00 2001
 From: "Richard W.M. Jones" <rjones at redhat.com>
 Date: Tue, 19 Aug 2014 18:56:28 +0100
-Subject: [PATCH 02/11] aarch64: Allow -kernel option to take a gzip-compressed
+Subject: [PATCH] aarch64: Allow -kernel option to take a gzip-compressed
  kernel.
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
@@ -52,6 +51,3 @@ index 50b6c5c..4bad4e6 100644
      if (kernel_size < 0) {
          entry = info->loader_start + kernel_load_offset;
          kernel_size = load_image_targphys(info->kernel_filename, entry,
--- 
-2.1.0
-
diff --git a/0003-block.curl-adding-timeout-option.patch b/0003-block.curl-adding-timeout-option.patch
index d05e3d2..b003edf 100644
--- a/0003-block.curl-adding-timeout-option.patch
+++ b/0003-block.curl-adding-timeout-option.patch
@@ -1,7 +1,6 @@
-From 799d9c41ae5fd105e1467863dd912f8fd4e970bf Mon Sep 17 00:00:00 2001
 From: Daniel Henrique Barboza <danielhb at linux.vnet.ibm.com>
 Date: Wed, 13 Aug 2014 12:44:27 -0300
-Subject: [PATCH 03/11] block.curl: adding 'timeout' option
+Subject: [PATCH] block.curl: adding 'timeout' option
 
 The curl hardcoded timeout (5 seconds) sometimes is not long
 enough depending on the remote server configuration and network
@@ -111,6 +110,3 @@ index 1549625..dcb008b 100644
  
  qemu-system-x86_64 -drive file=/tmp/test.qcow2
  @end example
--- 
-2.1.0
-
diff --git a/0004-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch b/0004-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch
index 7a4d76a..e58b6e4 100644
--- a/0004-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch
+++ b/0004-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch
@@ -1,8 +1,7 @@
-From db1048a84b2cbf57809a5fcaebd567e8e9a209e4 Mon Sep 17 00:00:00 2001
 From: "Richard W.M. Jones" <rjones at redhat.com>
 Date: Fri, 29 Aug 2014 16:03:12 +0100
-Subject: [PATCH 04/11] curl: Allow a cookie or cookies to be sent with
- http/https requests.
+Subject: [PATCH] curl: Allow a cookie or cookies to be sent with http/https
+ requests.
 
 In order to access VMware ESX efficiently, we need to send a session
 cookie.  This patch is very simple and just allows you to send that
@@ -122,6 +121,3 @@ index dcb008b..53b6171 100644
  @item timeout
  Set the timeout in seconds of the CURL connection. This timeout is the time
  that CURL waits for a response from the remote server to get the size of the
--- 
-2.1.0
-
diff --git a/0005-curl-Don-t-deref-NULL-pointer-in-call-to-aio_poll.patch b/0005-curl-Don-t-deref-NULL-pointer-in-call-to-aio_poll.patch
index dd0a1e0..b00a751 100644
--- a/0005-curl-Don-t-deref-NULL-pointer-in-call-to-aio_poll.patch
+++ b/0005-curl-Don-t-deref-NULL-pointer-in-call-to-aio_poll.patch
@@ -1,7 +1,6 @@
-From 61fa004b207d01de98cd2aac6fe7b553da6fe079 Mon Sep 17 00:00:00 2001
 From: "Richard W.M. Jones" <rjones at redhat.com>
 Date: Thu, 28 Aug 2014 09:04:21 +0100
-Subject: [PATCH 05/11] curl: Don't deref NULL pointer in call to aio_poll.
+Subject: [PATCH] curl: Don't deref NULL pointer in call to aio_poll.
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
@@ -75,6 +74,3 @@ index 537e257..d28b701 100644
      if (!state) {
          acb->common.cb(acb->common.opaque, -EIO);
          qemu_aio_release(acb);
--- 
-2.1.0
-
diff --git a/0006-virtio-pci-fix-migration-for-pci-bus-master.patch b/0006-virtio-pci-fix-migration-for-pci-bus-master.patch
index 38b7fb0..98b050f 100644
--- a/0006-virtio-pci-fix-migration-for-pci-bus-master.patch
+++ b/0006-virtio-pci-fix-migration-for-pci-bus-master.patch
@@ -1,7 +1,6 @@
-From 5c8a5868a03d062a25a0345dc8c97358fd7ad6f9 Mon Sep 17 00:00:00 2001
 From: "Michael S. Tsirkin" <mst at redhat.com>
 Date: Thu, 11 Sep 2014 18:34:29 +0300
-Subject: [PATCH 06/11] virtio-pci: fix migration for pci bus master
+Subject: [PATCH] virtio-pci: fix migration for pci bus master
 
 Current support for bus master (clearing OK bit)
 together with the need to support guests which do not
@@ -115,6 +114,3 @@ index ba675fe..ec582fe 100644
  }
  
  static Property virtio_pci_properties[] = {
--- 
-2.1.0
-
diff --git a/0007-Revert-virtio-pci-fix-migration-for-pci-bus-master.patch b/0007-Revert-virtio-pci-fix-migration-for-pci-bus-master.patch
index 0227afa..1993a96 100644
--- a/0007-Revert-virtio-pci-fix-migration-for-pci-bus-master.patch
+++ b/0007-Revert-virtio-pci-fix-migration-for-pci-bus-master.patch
@@ -1,7 +1,6 @@
-From ff681d852d37fe9f1ac64076fc18ecc1b9b698da Mon Sep 17 00:00:00 2001
 From: "Michael S. Tsirkin" <mst at redhat.com>
 Date: Mon, 29 Sep 2014 11:27:32 +0300
-Subject: [PATCH 07/11] Revert "virtio-pci: fix migration for pci bus master"
+Subject: [PATCH] Revert "virtio-pci: fix migration for pci bus master"
 
 This reverts commit 4d43d3f3c8147ade184df9a1e9e82826edd39e19.
 
@@ -96,6 +95,3 @@ index ec582fe..ba675fe 100644
  }
  
  static Property virtio_pci_properties[] = {
--- 
-2.1.0
-
diff --git a/0008-block-raw-posix-Fix-disk-corruption-in-try_fiemap.patch b/0008-block-raw-posix-Fix-disk-corruption-in-try_fiemap.patch
index 14bb69e..49e4de3 100644
--- a/0008-block-raw-posix-Fix-disk-corruption-in-try_fiemap.patch
+++ b/0008-block-raw-posix-Fix-disk-corruption-in-try_fiemap.patch
@@ -1,7 +1,6 @@
-From af316039d3f1818463e8d5f8f4e5eaf19a2c7b55 Mon Sep 17 00:00:00 2001
 From: Tony Breeds <tony at bakeyournoodle.com>
 Date: Fri, 26 Sep 2014 09:14:11 +1000
-Subject: [PATCH 08/11] block/raw-posix: Fix disk corruption in try_fiemap
+Subject: [PATCH] block/raw-posix: Fix disk corruption in try_fiemap
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
@@ -40,6 +39,3 @@ index efa5686..8f6c923 100644
      f.fm.fm_extent_count = 1;
      f.fm.fm_reserved = 0;
      if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
--- 
-2.1.0
-
diff --git a/0009-block-raw-posix-use-seek_hole-ahead-of-fiemap.patch b/0009-block-raw-posix-use-seek_hole-ahead-of-fiemap.patch
index 57664a7..b8be43f 100644
--- a/0009-block-raw-posix-use-seek_hole-ahead-of-fiemap.patch
+++ b/0009-block-raw-posix-use-seek_hole-ahead-of-fiemap.patch
@@ -1,7 +1,6 @@
-From 1b66fe241d9609fed79ee1583e6425833a1d7d9e Mon Sep 17 00:00:00 2001
 From: Tony Breeds <tony at bakeyournoodle.com>
 Date: Fri, 26 Sep 2014 09:14:12 +1000
-Subject: [PATCH 09/11] block/raw-posix: use seek_hole ahead of fiemap
+Subject: [PATCH] block/raw-posix: use seek_hole ahead of fiemap
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
@@ -45,6 +44,3 @@ index 8f6c923..50d29e7 100644
          if (ret < 0) {
              /* Assume everything is allocated. */
              data = 0;
--- 
-2.1.0
-
diff --git a/0010-usb-host-fix-usb_host_speed_compat-tyops.patch b/0010-usb-host-fix-usb_host_speed_compat-tyops.patch
index 801306b..37ea3d3 100644
--- a/0010-usb-host-fix-usb_host_speed_compat-tyops.patch
+++ b/0010-usb-host-fix-usb_host_speed_compat-tyops.patch
@@ -1,7 +1,6 @@
-From 05c1cce68ef4eea1337f5d415f3b98a2f2283931 Mon Sep 17 00:00:00 2001
 From: Gerd Hoffmann <kraxel at redhat.com>
 Date: Mon, 10 Nov 2014 12:14:22 +0100
-Subject: [PATCH 10/11] usb-host: fix usb_host_speed_compat tyops
+Subject: [PATCH] usb-host: fix usb_host_speed_compat tyops
 
 Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
 Reviewed-by: Gonglei <arei.gonglei at huawei.com>
@@ -31,6 +30,3 @@ index c189147..69213e9 100644
      }
  }
  
--- 
-2.1.0
-
diff --git a/0011-block-Fix-max-nb_sectors-in-bdrv_make_zero.patch b/0011-block-Fix-max-nb_sectors-in-bdrv_make_zero.patch
deleted file mode 100644
index 3eedd00..0000000
--- a/0011-block-Fix-max-nb_sectors-in-bdrv_make_zero.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From a7cb55181edfc1e328027916e54d873c7eb85421 Mon Sep 17 00:00:00 2001
-From: Fam Zheng <famz at redhat.com>
-Date: Mon, 10 Nov 2014 15:07:44 +0800
-Subject: [PATCH 11/11] block: Fix max nb_sectors in bdrv_make_zero
-
-In bdrv_rw_co we report -EINVAL for nb_sectors > INT_MAX /
-BDRV_SECTOR_SIZE, so a caller shouldn't exceed it.
-
-Signed-off-by: Fam Zheng <famz at redhat.com>
-Reviewed-by: Markus Armbruster <armbru at redhat.com>
-Message-id: 1415603264-21497-1-git-send-email-famz at redhat.com
-Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
----
- block.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/block.c b/block.c
-index ed87b7e..8dc841c 100644
---- a/block.c
-+++ b/block.c
-@@ -2834,8 +2834,8 @@ int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
-         if (nb_sectors <= 0) {
-             return 0;
-         }
--        if (nb_sectors > INT_MAX) {
--            nb_sectors = INT_MAX;
-+        if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
-+            nb_sectors = INT_MAX / BDRV_SECTOR_SIZE;
-         }
-         ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n);
-         if (ret < 0) {
--- 
-2.1.0
-
diff --git a/0011-ide-Correct-handling-of-malformed-short-PRDTs.patch b/0011-ide-Correct-handling-of-malformed-short-PRDTs.patch
new file mode 100644
index 0000000..6f9a295
--- /dev/null
+++ b/0011-ide-Correct-handling-of-malformed-short-PRDTs.patch
@@ -0,0 +1,335 @@
+From: John Snow <jsnow at redhat.com>
+Date: Fri, 31 Oct 2014 16:03:39 -0400
+Subject: [PATCH] ide: Correct handling of malformed/short PRDTs
+
+This impacts both BMDMA and AHCI HBA interfaces for IDE.
+Currently, we confuse the difference between a PRDT having
+"0 bytes" and a PRDT having "0 complete sectors."
+
+When we receive an incomplete sector, inconsistent error checking
+leads to an infinite loop wherein the call succeeds, but it
+didn't give us enough bytes -- leading us to re-call the
+DMA chain over and over again. This leads to, in the BMDMA case,
+leaked memory for short PRDTs, and infinite loops and resource
+usage in the AHCI case.
+
+The .prepare_buf() callback is reworked to return the number of
+bytes that it successfully prepared. 0 is a valid, non-error
+answer that means the table was empty and described no bytes.
+-1 indicates an error.
+
+Our current implementation uses the io_buffer in IDEState to
+ultimately describe the size of a prepared scatter-gather list.
+Even though the AHCI PRDT/SGList can be as large as 256GiB, the
+AHCI command header limits transactions to just 4GiB. ATA8-ACS3,
+however, defines the largest transaction to be an LBA48 command
+that transfers 65,536 sectors. With a 512 byte sector size, this
+is just 32MiB.
+
+Since our current state structures use the int type to describe
+the size of the buffer, and this state is migrated as int32, we
+are limited to describing 2GiB buffer sizes unless we change the
+migration protocol.
+
+For this reason, this patch begins to unify the assertions in the
+IDE pathways that the scatter-gather list provided by either the
+AHCI PRDT or the PCI BMDMA PRDs can only describe, at a maximum,
+2GiB. This should be resilient enough unless we need a sector
+size that exceeds 32KiB.
+
+Further, the likelihood of any guest operating system actually
+attempting to transfer this much data in a single operation is
+very slim.
+
+To this end, the IDEState variables have been updated to more
+explicitly clarify our maximum supported size. Callers to the
+prepare_buf callback have been reworked to understand the new
+return code, and all versions of the prepare_buf callback have
+been adjusted accordingly.
+
+Lastly, the ahci_populate_sglist helper, relied upon by the
+AHCI implementation of .prepare_buf() as well as the PCI
+implementation of the callback have had overflow assertions
+added to help make clear the reasonings behind the various
+type changes.
+
+[Added %d -> %"PRId64" fix John sent because off_pos changed from int to
+int64_t.
+--Stefan]
+
+Signed-off-by: John Snow <jsnow at redhat.com>
+Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
+Message-id: 1414785819-26209-4-git-send-email-jsnow at redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
+(cherry picked from commit 3251bdcf1c67427d964517053c3d185b46e618e8)
+---
+ hw/ide/ahci.c     | 33 ++++++++++++++++++++++++++-------
+ hw/ide/core.c     | 10 ++++++++--
+ hw/ide/internal.h | 13 +++++++------
+ hw/ide/macio.c    |  7 ++++++-
+ hw/ide/pci.c      | 27 +++++++++++++++++++++------
+ 5 files changed, 68 insertions(+), 22 deletions(-)
+
+diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
+index 604152a..9674f5f 100644
+--- a/hw/ide/ahci.c
++++ b/hw/ide/ahci.c
+@@ -645,7 +645,8 @@ static int prdt_tbl_entry_size(const AHCI_SG *tbl)
+     return (le32_to_cpu(tbl->flags_size) & AHCI_PRDT_SIZE_MASK) + 1;
+ }
+ 
+-static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
++static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist,
++                                int32_t offset)
+ {
+     AHCICmdHdr *cmd = ad->cur_cmd;
+     uint32_t opts = le32_to_cpu(cmd->opts);
+@@ -656,13 +657,21 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
+     uint8_t *prdt;
+     int i;
+     int r = 0;
+-    int sum = 0;
++    uint64_t sum = 0;
+     int off_idx = -1;
+-    int off_pos = -1;
++    int64_t off_pos = -1;
+     int tbl_entry_size;
+     IDEBus *bus = &ad->port;
+     BusState *qbus = BUS(bus);
+ 
++    /*
++     * Note: AHCI PRDT can describe up to 256GiB. SATA/ATA only support
++     * transactions of up to 32MiB as of ATA8-ACS3 rev 1b, assuming a
++     * 512 byte sector size. We limit the PRDT in this implementation to
++     * a reasonably large 2GiB, which can accommodate the maximum transfer
++     * request for sector sizes up to 32K.
++     */
++
+     if (!sglist_alloc_hint) {
+         DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
+         return -1;
+@@ -697,7 +706,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
+         }
+         if ((off_idx == -1) || (off_pos < 0) || (off_pos > tbl_entry_size)) {
+             DPRINTF(ad->port_no, "%s: Incorrect offset! "
+-                            "off_idx: %d, off_pos: %d\n",
++                            "off_idx: %d, off_pos: %"PRId64"\n",
+                             __func__, off_idx, off_pos);
+             r = -1;
+             goto out;
+@@ -712,6 +721,13 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
+             /* flags_size is zero-based */
+             qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr),
+                             prdt_tbl_entry_size(&tbl[i]));
++            if (sglist->size > INT32_MAX) {
++                error_report("AHCI Physical Region Descriptor Table describes "
++                             "more than 2 GiB.\n");
++                qemu_sglist_destroy(sglist);
++                r = -1;
++                goto out;
++            }
+         }
+     }
+ 
+@@ -1056,16 +1072,19 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s,
+     dma_cb(s, 0);
+ }
+ 
+-static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write)
++static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int is_write)
+ {
+     AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
+     IDEState *s = &ad->port.ifs[0];
+ 
+-    ahci_populate_sglist(ad, &s->sg, 0);
++    if (ahci_populate_sglist(ad, &s->sg, 0) == -1) {
++        DPRINTF(ad->port_no, "ahci_dma_prepare_buf failed.\n");
++        return -1;
++    }
+     s->io_buffer_size = s->sg.size;
+ 
+     DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size);
+-    return s->io_buffer_size != 0;
++    return s->io_buffer_size;
+ }
+ 
+ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index fa4cafa..50691fc 100644
+--- a/hw/ide/core.c
++++ b/hw/ide/core.c
+@@ -676,10 +676,11 @@ void ide_dma_cb(void *opaque, int ret)
+     n = s->nsector;
+     s->io_buffer_index = 0;
+     s->io_buffer_size = n * 512;
+-    if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0) {
++    if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) < 512) {
+         /* The PRDs were too short. Reset the Active bit, but don't raise an
+          * interrupt. */
+         s->status = READY_STAT | SEEK_STAT;
++        dma_buf_commit(s);
+         goto eot;
+     }
+ 
+@@ -2212,6 +2213,11 @@ static int ide_nop_int(IDEDMA *dma, int x)
+     return 0;
+ }
+ 
++static int32_t ide_nop_int32(IDEDMA *dma, int x)
++{
++    return 0;
++}
++
+ static void ide_nop_restart(void *opaque, int x, RunState y)
+ {
+ }
+@@ -2219,7 +2225,7 @@ static void ide_nop_restart(void *opaque, int x, RunState y)
+ static const IDEDMAOps ide_dma_nop_ops = {
+     .start_dma      = ide_nop_start,
+     .start_transfer = ide_nop,
+-    .prepare_buf    = ide_nop_int,
++    .prepare_buf    = ide_nop_int32,
+     .rw_buf         = ide_nop_int,
+     .set_unit       = ide_nop_int,
+     .add_status     = ide_nop_int,
+diff --git a/hw/ide/internal.h b/hw/ide/internal.h
+index 0567a52..b03045b 100644
+--- a/hw/ide/internal.h
++++ b/hw/ide/internal.h
+@@ -322,6 +322,7 @@ typedef void EndTransferFunc(IDEState *);
+ typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *);
+ typedef int DMAFunc(IDEDMA *);
+ typedef int DMAIntFunc(IDEDMA *, int);
++typedef int32_t DMAInt32Func(IDEDMA *, int);
+ typedef void DMARestartFunc(void *, int, RunState);
+ 
+ struct unreported_events {
+@@ -383,7 +384,7 @@ struct IDEState {
+     uint8_t cdrom_changed;
+     int packet_transfer_size;
+     int elementary_transfer_size;
+-    int io_buffer_index;
++    int32_t io_buffer_index;
+     int lba;
+     int cd_sector_size;
+     int atapi_dma; /* true if dma is requested for the packet cmd */
+@@ -392,8 +393,8 @@ struct IDEState {
+     struct iovec iov;
+     QEMUIOVector qiov;
+     /* ATA DMA state */
+-    int io_buffer_offset;
+-    int io_buffer_size;
++    int32_t io_buffer_offset;
++    int32_t io_buffer_size;
+     QEMUSGList sg;
+     /* PIO transfer handling */
+     int req_nb_sectors; /* number of sectors per interrupt */
+@@ -403,8 +404,8 @@ struct IDEState {
+     uint8_t *io_buffer;
+     /* PIO save/restore */
+     int32_t io_buffer_total_len;
+-    int cur_io_buffer_offset;
+-    int cur_io_buffer_len;
++    int32_t cur_io_buffer_offset;
++    int32_t cur_io_buffer_len;
+     uint8_t end_transfer_fn_idx;
+     QEMUTimer *sector_write_timer; /* only used for win2k install hack */
+     uint32_t irq_count; /* counts IRQs when using win2k install hack */
+@@ -428,7 +429,7 @@ struct IDEState {
+ struct IDEDMAOps {
+     DMAStartFunc *start_dma;
+     DMAFunc *start_transfer;
+-    DMAIntFunc *prepare_buf;
++    DMAInt32Func *prepare_buf;
+     DMAIntFunc *rw_buf;
+     DMAIntFunc *set_unit;
+     DMAIntFunc *add_status;
+diff --git a/hw/ide/macio.c b/hw/ide/macio.c
+index c14a1dd..68d88ac 100644
+--- a/hw/ide/macio.c
++++ b/hw/ide/macio.c
+@@ -555,6 +555,11 @@ static int ide_nop_int(IDEDMA *dma, int x)
+     return 0;
+ }
+ 
++static int32_t ide_nop_int32(IDEDMA *dma, int x)
++{
++    return 0;
++}
++
+ static void ide_nop_restart(void *opaque, int x, RunState y)
+ {
+ }
+@@ -572,7 +577,7 @@ static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
+ static const IDEDMAOps dbdma_ops = {
+     .start_dma      = ide_dbdma_start,
+     .start_transfer = ide_nop,
+-    .prepare_buf    = ide_nop_int,
++    .prepare_buf    = ide_nop_int32,
+     .rw_buf         = ide_nop_int,
+     .set_unit       = ide_nop_int,
+     .add_status     = ide_nop_int,
+diff --git a/hw/ide/pci.c b/hw/ide/pci.c
+index 6257a21..6591246 100644
+--- a/hw/ide/pci.c
++++ b/hw/ide/pci.c
+@@ -28,7 +28,7 @@
+ #include <hw/isa/isa.h>
+ #include "block/block.h"
+ #include "sysemu/dma.h"
+-
++#include "qemu/error-report.h"
+ #include <hw/ide/pci.h>
+ 
+ #define BMDMA_PAGE_SIZE 4096
+@@ -51,8 +51,11 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s,
+     }
+ }
+ 
+-/* return 0 if buffer completed */
+-static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
++/**
++ * Return the number of bytes successfully prepared.
++ * -1 on error.
++ */
++static int32_t bmdma_prepare_buf(IDEDMA *dma, int is_write)
+ {
+     BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
+     IDEState *s = bmdma_active_if(bm);
+@@ -70,8 +73,9 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
+         if (bm->cur_prd_len == 0) {
+             /* end of table (with a fail safe of one page) */
+             if (bm->cur_prd_last ||
+-                (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
+-                return s->io_buffer_size != 0;
++                (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) {
++                return s->io_buffer_size;
++            }
+             pci_dma_read(pci_dev, bm->cur_addr, &prd, 8);
+             bm->cur_addr += 8;
+             prd.addr = le32_to_cpu(prd.addr);
+@@ -86,12 +90,23 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write)
+         l = bm->cur_prd_len;
+         if (l > 0) {
+             qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);
++
++            /* Note: We limit the max transfer to be 2GiB.
++             * This should accommodate the largest ATA transaction
++             * for LBA48 (65,536 sectors) and 32K sector sizes. */
++            if (s->sg.size > INT32_MAX) {
++                error_report("IDE: sglist describes more than 2GiB.\n");
++                break;
++            }
+             bm->cur_prd_addr += l;
+             bm->cur_prd_len -= l;
+             s->io_buffer_size += l;
+         }
+     }
+-    return 1;
++
++    qemu_sglist_destroy(&s->sg);
++    s->io_buffer_size = 0;
++    return -1;
+ }
+ 
+ /* return 0 if buffer completed */
diff --git a/0012-cirrus-fix-blit-region-check.patch b/0012-cirrus-fix-blit-region-check.patch
new file mode 100644
index 0000000..8b88e39
--- /dev/null
+++ b/0012-cirrus-fix-blit-region-check.patch
@@ -0,0 +1,122 @@
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Wed, 19 Nov 2014 11:37:42 +0100
+Subject: [PATCH] cirrus: fix blit region check
+
+Issues:
+ * Doesn't check pitches correctly in case it is negative.
+ * Doesn't check width at all.
+
+Turn macro into functions while being at it, also factor out the check
+for one region which we then can simply call twice for src + dst.
+
+This is CVE-2014-8106.
+
+Reported-by: Paolo Bonzini <pbonzini at redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
+Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
+(cherry picked from commit d3532a0db02296e687711b8cdc7791924efccea0)
+---
+ hw/display/cirrus_vga.c | 61 +++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 44 insertions(+), 17 deletions(-)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index db330e9..44b2b7c 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -172,20 +172,6 @@
+ 
+ #define CIRRUS_PNPMMIO_SIZE         0x1000
+ 
+-#define BLTUNSAFE(s) \
+-    ( \
+-        ( /* check dst is within bounds */ \
+-            (s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \
+-                + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
+-                    (s)->vga.vram_size \
+-        ) || \
+-        ( /* check src is within bounds */ \
+-            (s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \
+-                + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
+-                    (s)->vga.vram_size \
+-        ) \
+-    )
+-
+ struct CirrusVGAState;
+ typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
+                                      uint8_t * dst, const uint8_t * src,
+@@ -278,6 +264,46 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
+  *
+  ***************************************/
+ 
++static bool blit_region_is_unsafe(struct CirrusVGAState *s,
++                                  int32_t pitch, int32_t addr)
++{
++    if (pitch < 0) {
++        int64_t min = addr
++            + ((int64_t)s->cirrus_blt_height-1) * pitch;
++        int32_t max = addr
++            + s->cirrus_blt_width;
++        if (min < 0 || max >= s->vga.vram_size) {
++            return true;
++        }
++    } else {
++        int64_t max = addr
++            + ((int64_t)s->cirrus_blt_height-1) * pitch
++            + s->cirrus_blt_width;
++        if (max >= s->vga.vram_size) {
++            return true;
++        }
++    }
++    return false;
++}
++
++static bool blit_is_unsafe(struct CirrusVGAState *s)
++{
++    /* should be the case, see cirrus_bitblt_start */
++    assert(s->cirrus_blt_width > 0);
++    assert(s->cirrus_blt_height > 0);
++
++    if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
++                              s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
++        return true;
++    }
++    if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
++                              s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {
++        return true;
++    }
++
++    return false;
++}
++
+ static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
+                                   uint8_t *dst,const uint8_t *src,
+                                   int dstpitch,int srcpitch,
+@@ -635,7 +661,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
+ 
+     dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
+ 
+-    if (BLTUNSAFE(s))
++    if (blit_is_unsafe(s))
+         return 0;
+ 
+     (*s->cirrus_rop) (s, dst, src,
+@@ -653,8 +679,9 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
+ {
+     cirrus_fill_t rop_func;
+ 
+-    if (BLTUNSAFE(s))
++    if (blit_is_unsafe(s)) {
+         return 0;
++    }
+     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+     rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+              s->cirrus_blt_dstpitch,
+@@ -751,7 +778,7 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ 
+ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
+ {
+-    if (BLTUNSAFE(s))
++    if (blit_is_unsafe(s))
+         return 0;
+ 
+     cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
diff --git a/0013-cirrus-don-t-overflow-CirrusVGAState-cirrus_bltbuf.patch b/0013-cirrus-don-t-overflow-CirrusVGAState-cirrus_bltbuf.patch
new file mode 100644
index 0000000..ff8301b
--- /dev/null
+++ b/0013-cirrus-don-t-overflow-CirrusVGAState-cirrus_bltbuf.patch
@@ -0,0 +1,27 @@
+From: Gerd Hoffmann <kraxel at redhat.com>
+Date: Wed, 19 Nov 2014 13:27:28 +0100
+Subject: [PATCH] cirrus: don't overflow CirrusVGAState->cirrus_bltbuf
+
+This is CVE-2014-8106.
+
+Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
+(cherry picked from commit bf25983345ca44aec3dd92c57142be45452bd38a)
+---
+ hw/display/cirrus_vga.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
+index 44b2b7c..efa0969 100644
+--- a/hw/display/cirrus_vga.c
++++ b/hw/display/cirrus_vga.c
+@@ -292,6 +292,10 @@ static bool blit_is_unsafe(struct CirrusVGAState *s)
+     assert(s->cirrus_blt_width > 0);
+     assert(s->cirrus_blt_height > 0);
+ 
++    if (s->cirrus_blt_width > CIRRUS_BLTBUFSIZE) {
++        return true;
++    }
++
+     if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
+                               s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
+         return true;
diff --git a/0014-block-vdi-Add-locking-for-parallel-requests.patch b/0014-block-vdi-Add-locking-for-parallel-requests.patch
new file mode 100644
index 0000000..168d816
--- /dev/null
+++ b/0014-block-vdi-Add-locking-for-parallel-requests.patch
@@ -0,0 +1,84 @@
+From: Max Reitz <mreitz at redhat.com>
+Date: Fri, 27 Feb 2015 14:54:39 -0500
+Subject: [PATCH] block/vdi: Add locking for parallel requests
+
+When allocating a new cluster, the first write to it must be the one
+doing the allocation, because that one pads its write request to the
+cluster size; if another write to that cluster is executed before it,
+that write will be overwritten due to the padding.
+
+See https://bugs.launchpad.net/qemu/+bug/1422307 for what can go wrong
+without this patch.
+
+Cc: qemu-stable <qemu-stable at nongnu.org>
+Signed-off-by: Max Reitz <mreitz at redhat.com>
+Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
+Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
+Signed-off-by: Kevin Wolf <kwolf at redhat.com>
+(cherry picked from commit f0ab6f109630940146cbaf47d0cd99993ddba824)
+---
+ block/vdi.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/block/vdi.c b/block/vdi.c
+index 197bd77..4bfb510 100644
+--- a/block/vdi.c
++++ b/block/vdi.c
+@@ -53,6 +53,7 @@
+ #include "block/block_int.h"
+ #include "qemu/module.h"
+ #include "migration/migration.h"
++#include "block/coroutine.h"
+ #ifdef __linux__
+ #include <linux/fs.h>
+ #include <sys/ioctl.h>
+@@ -191,6 +192,8 @@ typedef struct {
+     /* VDI header (converted to host endianness). */
+     VdiHeader header;
+ 
++    CoMutex write_lock;
++
+     Error *migration_blocker;
+ } BDRVVdiState;
+ 
+@@ -490,6 +493,8 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
+               "vdi", bs->device_name, "live migration");
+     migrate_add_blocker(s->migration_blocker);
+ 
++    qemu_co_mutex_init(&s->write_lock);
++
+     return 0;
+ 
+  fail_free_bmap:
+@@ -625,11 +630,31 @@ static int vdi_co_write(BlockDriverState *bs,
+                    buf, n_sectors * SECTOR_SIZE);
+             memset(block + (sector_in_block + n_sectors) * SECTOR_SIZE, 0,
+                    (s->block_sectors - n_sectors - sector_in_block) * SECTOR_SIZE);
++
++            /* Note that this coroutine does not yield anywhere from reading the
++             * bmap entry until here, so in regards to all the coroutines trying
++             * to write to this cluster, the one doing the allocation will
++             * always be the first to try to acquire the lock.
++             * Therefore, it is also the first that will actually be able to
++             * acquire the lock and thus the padded cluster is written before
++             * the other coroutines can write to the affected area. */
++            qemu_co_mutex_lock(&s->write_lock);
+             ret = bdrv_write(bs->file, offset, block, s->block_sectors);
++            qemu_co_mutex_unlock(&s->write_lock);
+         } else {
+             uint64_t offset = s->header.offset_data / SECTOR_SIZE +
+                               (uint64_t)bmap_entry * s->block_sectors +
+                               sector_in_block;
++            qemu_co_mutex_lock(&s->write_lock);
++            /* This lock is only used to make sure the following write operation
++             * is executed after the write issued by the coroutine allocating
++             * this cluster, therefore we do not need to keep it locked.
++             * As stated above, the allocating coroutine will always try to lock
++             * the mutex before all the other concurrent accesses to that
++             * cluster, therefore at this point we can be absolutely certain
++             * that that write operation has returned (there may be other writes
++             * in flight, but they do not concern this very operation). */
++            qemu_co_mutex_unlock(&s->write_lock);
+             ret = bdrv_write(bs->file, offset, buf, n_sectors);
+         }
+ 
diff --git a/qemu.spec b/qemu.spec
index cdd30d5..3d1de4c 100644
--- a/qemu.spec
+++ b/qemu.spec
@@ -152,7 +152,7 @@
 Summary: QEMU is a FAST! processor emulator
 Name: qemu
 Version: 2.1.3
-Release: 3%{?dist}
+Release: 4%{?dist}
 Epoch: 2
 License: GPLv2+ and LGPLv2+ and BSD
 Group: Development/Tools
@@ -207,8 +207,14 @@ Patch0008: 0008-block-raw-posix-Fix-disk-corruption-in-try_fiemap.patch
 Patch0009: 0009-block-raw-posix-use-seek_hole-ahead-of-fiemap.patch
 # Fix USB host assignment (bz #1187749)
 Patch0010: 0010-usb-host-fix-usb_host_speed_compat-tyops.patch
-# Fix  qemu-img error (bz #1200043)
-Patch0011: 0011-block-Fix-max-nb_sectors-in-bdrv_make_zero.patch
+# Qemu: PRDT overflow from guest to host (bz #1204919, bz #1205322)
+Patch0011: 0011-ide-Correct-handling-of-malformed-short-PRDTs.patch
+# CVE-2014-8106: cirrus: insufficient blit region checks (bz #1170612,
+# bz #1169454)
+Patch0012: 0012-cirrus-fix-blit-region-check.patch
+Patch0013: 0013-cirrus-don-t-overflow-CirrusVGAState-cirrus_bltbuf.patch
+# Fix .vdi disk corruption (bz #1199400)
+Patch0014: 0014-block-vdi-Add-locking-for-parallel-requests.patch
 
 BuildRequires: SDL2-devel
 BuildRequires: zlib-devel
@@ -750,8 +756,14 @@ CAC emulation development files.
 %patch0009 -p1
 # Fix USB host assignment (bz #1187749)
 %patch0010 -p1
-# Fix qemu-img error (bz #1200043)
+# Qemu: PRDT overflow from guest to host (bz #1204919, bz #1205322)
 %patch0011 -p1
+# CVE-2014-8106: cirrus: insufficient blit region checks (bz #1170612,
+# bz #1169454)
+%patch0012 -p1
+%patch0013 -p1
+# Fix .vdi disk corruption (bz #1199400)
+%patch0014 -p1
 
 
 %build
@@ -864,11 +876,11 @@ if [ -x "$b" ]; then "$b" -help; fi
 
 %define _udevdir /lib/udev/rules.d
 
-install -D -p -m 0744 %{SOURCE4} $RPM_BUILD_ROOT/lib/systemd/system/ksm.service
+install -D -p -m 0644 %{SOURCE4} $RPM_BUILD_ROOT/lib/systemd/system/ksm.service
 install -D -p -m 0644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ksm
 install -D -p -m 0755 ksmctl $RPM_BUILD_ROOT/lib/systemd/ksmctl
 
-install -D -p -m 0744 %{SOURCE7} $RPM_BUILD_ROOT/lib/systemd/system/ksmtuned.service
+install -D -p -m 0644 %{SOURCE7} $RPM_BUILD_ROOT/lib/systemd/system/ksmtuned.service
 install -D -p -m 0755 %{SOURCE8} $RPM_BUILD_ROOT%{_sbindir}/ksmtuned
 install -D -p -m 0644 %{SOURCE9} $RPM_BUILD_ROOT%{_sysconfdir}/ksmtuned.conf
 
@@ -1532,6 +1544,13 @@ getent passwd qemu >/dev/null || \
 %endif
 
 %changelog
+* Fri Mar 27 2015 Cole Robinson <crobinso at redhat.com> - 2:2.1.3-4
+- Qemu: PRDT overflow from guest to host (bz #1204919, bz #1205322)
+- CVE-2014-8106: cirrus: insufficient blit region checks (bz #1170612, bz
+  #1169454)
+- Fix .vdi disk corruption (bz #1199400)
+- Don't install ksm services as executable (bz #1192720)
+
 * Tue Mar 10 2015 Haïkel Guémar <hguemar at fedoraproject.org> - 2:2.1.3-3
 - Backport upstream patch fixing some qemu-img conversion errors (RHBZ#1200043)
 
-- 
cgit v0.10.2


	http://pkgs.fedoraproject.org/cgit/qemu.git/commit/?h=f21&id=29e31e320f42ace6782d16ddf552d3540b28a9c3


More information about the scm-commits mailing list