[qemu/f20] Migration CVEs: CVE-2014-0182 etc.

Cole Robinson crobinso at fedoraproject.org
Sun May 11 22:43:28 UTC 2014


commit e976b467c3b81d403e9a37455dcafbe812d80848
Author: Cole Robinson <crobinso at redhat.com>
Date:   Sun May 11 18:43:54 2014 -0400

    Migration CVEs: CVE-2014-0182 etc.

 0301-vmstate-add-VMS_MUST_EXIST.patch              |   57 +++++++++++++++
 0302-vmstate-add-VMSTATE_VALIDATE.patch            |   33 +++++++++
 ...fix-buffer-overflow-on-invalid-state-load.patch |   59 +++++++++++++++
 ...out-of-bounds-buffer-write-on-invalid-sta.patch |   55 ++++++++++++++
 ...of-bounds-buffer-write-on-invalid-state-l.patch |   52 +++++++++++++
 ...-fix-buffer-overrun-on-invalid-state-load.patch |   36 +++++++++
 ...-fix-buffer-overrun-on-invalid-state-load.patch |   51 +++++++++++++
 ..._aer.c-fix-buffer-overruns-on-invalid-sta.patch |   55 ++++++++++++++
 ...2-fix-buffer-overun-on-invalid-state-load.patch |   50 +++++++++++++
 ...x-buffer-overflow-in-target-arm-machine.c.patch |   58 +++++++++++++++
 ...void-buffer-overrun-on-incoming-migration.patch |   40 ++++++++++
 0312-virtio-validate-num_sg-when-mapping.patch     |   41 +++++++++++
 ...void-buffer-overrun-on-incoming-migration.patch |   51 +++++++++++++
 ...3-fix-buffer-overun-on-invalid-state-load.patch |   77 ++++++++++++++++++++
 ...-fix-buffer-overrun-on-invalid-state-load.patch |   50 +++++++++++++
 ...-fix-buffer-overrun-on-invalid-state-load.patch |   54 ++++++++++++++
 ...-fix-buffer-overrun-on-invalid-state-load.patch |   67 +++++++++++++++++
 ...MSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch |   65 +++++++++++++++++
 ...-check-setup_index-setup_len-in-post_load.patch |   40 ++++++++++
 ...-fix-buffer-overrun-on-invalid-state-load.patch |   41 +++++++++++
 ...void-buffer-overrun-on-incoming-migration.patch |   72 ++++++++++++++++++
 ...io-net-out-of-bounds-buffer-write-on-load.patch |   55 ++++++++++++++
 0323-virtio-validate-config_len-on-load.patch      |   52 +++++++++++++
 qemu.spec                                          |   55 ++++++++++++++-
 24 files changed, 1265 insertions(+), 1 deletions(-)
---
diff --git a/0301-vmstate-add-VMS_MUST_EXIST.patch b/0301-vmstate-add-VMS_MUST_EXIST.patch
new file mode 100644
index 0000000..09ab522
--- /dev/null
+++ b/0301-vmstate-add-VMS_MUST_EXIST.patch
@@ -0,0 +1,57 @@
+From e8e3f1c084317c8bb184b75c19f9cb5473b9b7c9 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:50:31 +0300
+Subject: [PATCH] vmstate: add VMS_MUST_EXIST
+
+Can be used to verify a required field exists or validate
+state in some other way.
+
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 5bf81c8d63db0216a4d29dc87f9ce530bb791dd1)
+---
+ include/migration/vmstate.h |  1 +
+ savevm.c                    | 10 ++++++++++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
+index e5538c7..c1717c2 100644
+--- a/include/migration/vmstate.h
++++ b/include/migration/vmstate.h
+@@ -100,6 +100,7 @@ enum VMStateFlags {
+     VMS_MULTIPLY         = 0x200,  /* multiply "size" field by field_size */
+     VMS_VARRAY_UINT8     = 0x400,  /* Array with size in uint8_t field*/
+     VMS_VARRAY_UINT32    = 0x800,  /* Array with size in uint32_t field*/
++    VMS_MUST_EXIST       = 0x1000, /* Field must exist in input */
+ };
+ 
+ typedef struct {
+diff --git a/savevm.c b/savevm.c
+index 03fc4d9..9f7f668 100644
+--- a/savevm.c
++++ b/savevm.c
+@@ -1731,6 +1731,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
+                     return ret;
+                 }
+             }
++        } else if (field->flags & VMS_MUST_EXIST) {
++            fprintf(stderr, "Input validation failed: %s/%s\n",
++                    vmsd->name, field->name);
++            return -1;
+         }
+         field++;
+     }
+@@ -1791,6 +1795,12 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
+                     field->info->put(f, addr, size);
+                 }
+             }
++        } else {
++            if (field->flags & VMS_MUST_EXIST) {
++                fprintf(stderr, "Output state validation failed: %s/%s\n",
++                        vmsd->name, field->name);
++                assert(!(field->flags & VMS_MUST_EXIST));
++            }
+         }
+         field++;
+     }
diff --git a/0302-vmstate-add-VMSTATE_VALIDATE.patch b/0302-vmstate-add-VMSTATE_VALIDATE.patch
new file mode 100644
index 0000000..34ff9c8
--- /dev/null
+++ b/0302-vmstate-add-VMSTATE_VALIDATE.patch
@@ -0,0 +1,33 @@
+From 56a72d13f8dc547818c966fcf4d01819c8124b33 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:50:35 +0300
+Subject: [PATCH] vmstate: add VMSTATE_VALIDATE
+
+Validate state using VMS_ARRAY with num = 0 and VMS_MUST_EXIST
+
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 4082f0889ba04678fc14816c53e1b9251ea9207e)
+---
+ include/migration/vmstate.h | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
+index c1717c2..d5a63ce 100644
+--- a/include/migration/vmstate.h
++++ b/include/migration/vmstate.h
+@@ -204,6 +204,14 @@ extern const VMStateInfo vmstate_info_bitmap;
+     .offset       = vmstate_offset_value(_state, _field, _type),     \
+ }
+ 
++/* Validate state using a boolean predicate. */
++#define VMSTATE_VALIDATE(_name, _test) { \
++    .name         = (_name),                                         \
++    .field_exists = (_test),                                         \
++    .flags        = VMS_ARRAY | VMS_MUST_EXIST,                      \
++    .num          = 0, /* 0 elements: no data, only run _test */     \
++}
++
+ #define VMSTATE_POINTER(_field, _state, _version, _info, _type) {    \
+     .name       = (stringify(_field)),                               \
+     .version_id = (_version),                                        \
diff --git a/0303-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch b/0303-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch
new file mode 100644
index 0000000..c6a81de
--- /dev/null
+++ b/0303-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch
@@ -0,0 +1,59 @@
+From 0e8bff015d09d58e1b209368d9425a3293e9bc9e Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:50:39 +0300
+Subject: [PATCH] virtio-net: fix buffer overflow on invalid state load
+
+CVE-2013-4148 QEMU 1.0 integer conversion in
+virtio_net_load()@hw/net/virtio-net.c
+
+Deals with loading a corrupted savevm image.
+
+>         n->mac_table.in_use = qemu_get_be32(f);
+
+in_use is int so it can get negative when assigned 32bit unsigned value.
+
+>         /* MAC_TABLE_ENTRIES may be different from the saved image */
+>         if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
+
+passing this check ^^^
+
+>             qemu_get_buffer(f, n->mac_table.macs,
+>                             n->mac_table.in_use * ETH_ALEN);
+
+with good in_use value, "n->mac_table.in_use * ETH_ALEN" can get
+positive and bigger than mac_table.macs. For example 0x81000000
+satisfies this condition when ETH_ALEN is 6.
+
+Fix it by making the value unsigned.
+For consistency, change first_multi as well.
+
+Note: all call sites were audited to confirm that
+making them unsigned didn't cause any issues:
+it turns out we actually never do math on them,
+so it's easy to validate because both values are
+always <= MAC_TABLE_ENTRIES.
+
+Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Laszlo Ersek <lersek at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 71f7fe48e10a8437c9d42d859389f37157f59980)
+---
+ include/hw/virtio/virtio-net.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
+index df60f16..4b32440 100644
+--- a/include/hw/virtio/virtio-net.h
++++ b/include/hw/virtio/virtio-net.h
+@@ -176,8 +176,8 @@ typedef struct VirtIONet {
+     uint8_t nobcast;
+     uint8_t vhost_started;
+     struct {
+-        int in_use;
+-        int first_multi;
++        uint32_t in_use;
++        uint32_t first_multi;
+         uint8_t multi_overflow;
+         uint8_t uni_overflow;
+         uint8_t *macs;
diff --git a/0304-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch b/0304-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch
new file mode 100644
index 0000000..d5b4372
--- /dev/null
+++ b/0304-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch
@@ -0,0 +1,55 @@
+From 1f4b223bd7c6abe50dc0d3045365a6462cfb8a5e Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:50:56 +0300
+Subject: [PATCH] virtio-net: out-of-bounds buffer write on invalid state load
+
+CVE-2013-4150 QEMU 1.5.0 out-of-bounds buffer write in
+virtio_net_load()@hw/net/virtio-net.c
+
+This code is in hw/net/virtio-net.c:
+
+    if (n->max_queues > 1) {
+        if (n->max_queues != qemu_get_be16(f)) {
+            error_report("virtio-net: different max_queues ");
+            return -1;
+        }
+
+        n->curr_queues = qemu_get_be16(f);
+        for (i = 1; i < n->curr_queues; i++) {
+            n->vqs[i].tx_waiting = qemu_get_be32(f);
+        }
+    }
+
+Number of vqs is max_queues, so if we get invalid input here,
+for example if max_queues = 2, curr_queues = 3, we get
+write beyond end of the buffer, with data that comes from
+wire.
+
+This might be used to corrupt qemu memory in hard to predict ways.
+Since we have lots of function pointers around, RCE might be possible.
+
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Acked-by: Jason Wang <jasowang at redhat.com>
+Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit eea750a5623ddac7a61982eec8f1c93481857578)
+---
+ hw/net/virtio-net.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 63f777f..5907e96 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -1379,6 +1379,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
+         }
+ 
+         n->curr_queues = qemu_get_be16(f);
++        if (n->curr_queues > n->max_queues) {
++            error_report("virtio-net: curr_queues %x > max_queues %x",
++                         n->curr_queues, n->max_queues);
++            return -1;
++        }
+         for (i = 1; i < n->curr_queues; i++) {
+             n->vqs[i].tx_waiting = qemu_get_be32(f);
+         }
diff --git a/0305-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch b/0305-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch
new file mode 100644
index 0000000..67c2a12
--- /dev/null
+++ b/0305-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch
@@ -0,0 +1,52 @@
+From aa7a505a6ddfc7ae215adcbf49f9e135b8471643 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:14 +0300
+Subject: [PATCH] virtio: out-of-bounds buffer write on invalid state load
+
+CVE-2013-4151 QEMU 1.0 out-of-bounds buffer write in
+virtio_load at hw/virtio/virtio.c
+
+So we have this code since way back when:
+
+    num = qemu_get_be32(f);
+
+    for (i = 0; i < num; i++) {
+        vdev->vq[i].vring.num = qemu_get_be32(f);
+
+array of vqs has size VIRTIO_PCI_QUEUE_MAX, so
+on invalid input this will write beyond end of buffer.
+
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit cc45995294b92d95319b4782750a3580cabdbc0c)
+---
+ hw/virtio/virtio.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 965b2c0..8dc3cb3 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -888,7 +888,8 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val)
+ 
+ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
+ {
+-    int num, i, ret;
++    int i, ret;
++    uint32_t num;
+     uint32_t features;
+     uint32_t supported_features;
+     BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+@@ -916,6 +917,11 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
+ 
+     num = qemu_get_be32(f);
+ 
++    if (num > VIRTIO_PCI_QUEUE_MAX) {
++        error_report("Invalid number of PCI queues: 0x%x", num);
++        return -1;
++    }
++
+     for (i = 0; i < num; i++) {
+         vdev->vq[i].vring.num = qemu_get_be32(f);
+         if (k->has_variable_vring_alignment) {
diff --git a/0306-ahci-fix-buffer-overrun-on-invalid-state-load.patch b/0306-ahci-fix-buffer-overrun-on-invalid-state-load.patch
new file mode 100644
index 0000000..e11b091
--- /dev/null
+++ b/0306-ahci-fix-buffer-overrun-on-invalid-state-load.patch
@@ -0,0 +1,36 @@
+From 728aa9daeed4e45c7243fb3554dd4ae6e9ddd538 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:18 +0300
+Subject: [PATCH] ahci: fix buffer overrun on invalid state load
+
+CVE-2013-4526
+
+Within hw/ide/ahci.c, VARRAY refers to ports which is also loaded.  So
+we use the old version of ports to read the array but then allow any
+value for ports.  This can cause the code to overflow.
+
+There's no reason to migrate ports - it never changes.
+So just make sure it matches.
+
+Reported-by: Anthony Liguori <anthony at codemonkey.ws>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit ae2158ad6ce0845b2fae2a22aa7f19c0d7a71ce5)
+---
+ hw/ide/ahci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
+index bba150f..7c62cc7 100644
+--- a/hw/ide/ahci.c
++++ b/hw/ide/ahci.c
+@@ -1281,7 +1281,7 @@ const VMStateDescription vmstate_ahci = {
+         VMSTATE_UINT32(control_regs.impl, AHCIState),
+         VMSTATE_UINT32(control_regs.version, AHCIState),
+         VMSTATE_UINT32(idp_index, AHCIState),
+-        VMSTATE_INT32(ports, AHCIState),
++        VMSTATE_INT32_EQUAL(ports, AHCIState),
+         VMSTATE_END_OF_LIST()
+     },
+ };
diff --git a/0307-hpet-fix-buffer-overrun-on-invalid-state-load.patch b/0307-hpet-fix-buffer-overrun-on-invalid-state-load.patch
new file mode 100644
index 0000000..024354f
--- /dev/null
+++ b/0307-hpet-fix-buffer-overrun-on-invalid-state-load.patch
@@ -0,0 +1,51 @@
+From a969a34fbbf1e36225ba6bd7c0e54db2d13f8b66 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:23 +0300
+Subject: [PATCH] hpet: fix buffer overrun on invalid state load
+
+CVE-2013-4527 hw/timer/hpet.c buffer overrun
+
+hpet is a VARRAY with a uint8 size but static array of 32
+
+To fix, make sure num_timers is valid using VMSTATE_VALID hook.
+
+Reported-by: Anthony Liguori <anthony at codemonkey.ws>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 3f1c49e2136fa08ab1ef3183fd55def308829584)
+---
+ hw/timer/hpet.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
+index 648b383..d4d52f1 100644
+--- a/hw/timer/hpet.c
++++ b/hw/timer/hpet.c
+@@ -228,6 +228,18 @@ static int hpet_pre_load(void *opaque)
+     return 0;
+ }
+ 
++static bool hpet_validate_num_timers(void *opaque, int version_id)
++{
++    HPETState *s = opaque;
++
++    if (s->num_timers < HPET_MIN_TIMERS) {
++        return false;
++    } else if (s->num_timers > HPET_MAX_TIMERS) {
++        return false;
++    }
++    return true;
++}
++
+ static int hpet_post_load(void *opaque, int version_id)
+ {
+     HPETState *s = opaque;
+@@ -296,6 +308,7 @@ static const VMStateDescription vmstate_hpet = {
+         VMSTATE_UINT64(isr, HPETState),
+         VMSTATE_UINT64(hpet_counter, HPETState),
+         VMSTATE_UINT8_V(num_timers, HPETState, 2),
++        VMSTATE_VALIDATE("num_timers in range", hpet_validate_num_timers),
+         VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
+                                     vmstate_hpet_timer, HPETTimer),
+         VMSTATE_END_OF_LIST()
diff --git a/0308-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch b/0308-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch
new file mode 100644
index 0000000..5900bc0
--- /dev/null
+++ b/0308-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch
@@ -0,0 +1,55 @@
+From f749283b41d526bb07d0f87e8787e83b001e2471 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:31 +0300
+Subject: [PATCH] hw/pci/pcie_aer.c: fix buffer overruns on invalid state load
+
+4) CVE-2013-4529
+hw/pci/pcie_aer.c    pcie aer log can overrun the buffer if log_num is
+                     too large
+
+There are two issues in this file:
+1. log_max from remote can be larger than on local
+then buffer will overrun with data coming from state file.
+2. log_num can be larger then we get data corruption
+again with an overflow but not adversary controlled.
+
+Fix both issues.
+
+Reported-by: Anthony Liguori <anthony at codemonkey.ws>
+Reported-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 5f691ff91d323b6f97c6600405a7f9dc115a0ad1)
+---
+ hw/pci/pcie_aer.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
+index ca762ab..55083cd 100644
+--- a/hw/pci/pcie_aer.c
++++ b/hw/pci/pcie_aer.c
+@@ -795,6 +795,13 @@ static const VMStateDescription vmstate_pcie_aer_err = {
+     }
+ };
+ 
++static bool pcie_aer_state_log_num_valid(void *opaque, int version_id)
++{
++    PCIEAERLog *s = opaque;
++
++    return s->log_num <= s->log_max;
++}
++
+ const VMStateDescription vmstate_pcie_aer_log = {
+     .name = "PCIE_AER_ERROR_LOG",
+     .version_id = 1,
+@@ -802,7 +809,8 @@ const VMStateDescription vmstate_pcie_aer_log = {
+     .minimum_version_id_old = 1,
+     .fields     = (VMStateField[]) {
+         VMSTATE_UINT16(log_num, PCIEAERLog),
+-        VMSTATE_UINT16(log_max, PCIEAERLog),
++        VMSTATE_UINT16_EQUAL(log_max, PCIEAERLog),
++        VMSTATE_VALIDATE("log_num <= log_max", pcie_aer_state_log_num_valid),
+         VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
+                               vmstate_pcie_aer_err, PCIEAERErr),
+         VMSTATE_END_OF_LIST()
diff --git a/0309-pl022-fix-buffer-overun-on-invalid-state-load.patch b/0309-pl022-fix-buffer-overun-on-invalid-state-load.patch
new file mode 100644
index 0000000..212e88a
--- /dev/null
+++ b/0309-pl022-fix-buffer-overun-on-invalid-state-load.patch
@@ -0,0 +1,50 @@
+From 33890300408173e7322680ecd424d13f65b2e17d Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:35 +0300
+Subject: [PATCH] pl022: fix buffer overun on invalid state load
+
+CVE-2013-4530
+
+pl022.c did not bounds check tx_fifo_head and
+rx_fifo_head after loading them from file and
+before they are used to dereference array.
+
+Reported-by: Michael S. Tsirkin <mst at redhat.com
+Reported-by: Anthony Liguori <anthony at codemonkey.ws>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit d8d0a0bc7e194300e53a346d25fe5724fd588387)
+---
+ hw/ssi/pl022.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
+index fd479ef..b19bc71 100644
+--- a/hw/ssi/pl022.c
++++ b/hw/ssi/pl022.c
+@@ -240,11 +240,25 @@ static const MemoryRegionOps pl022_ops = {
+     .endianness = DEVICE_NATIVE_ENDIAN,
+ };
+ 
++static int pl022_post_load(void *opaque, int version_id)
++{
++    PL022State *s = opaque;
++
++    if (s->tx_fifo_head < 0 ||
++        s->tx_fifo_head >= ARRAY_SIZE(s->tx_fifo) ||
++        s->rx_fifo_head < 0 ||
++        s->rx_fifo_head >= ARRAY_SIZE(s->rx_fifo)) {
++        return -1;
++    }
++    return 0;
++}
++
+ static const VMStateDescription vmstate_pl022 = {
+     .name = "pl022_ssp",
+     .version_id = 1,
+     .minimum_version_id = 1,
+     .minimum_version_id_old = 1,
++    .post_load = pl022_post_load,
+     .fields      = (VMStateField[]) {
+         VMSTATE_UINT32(cr0, PL022State),
+         VMSTATE_UINT32(cr1, PL022State),
diff --git a/0310-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch b/0310-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch
new file mode 100644
index 0000000..3022e67
--- /dev/null
+++ b/0310-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch
@@ -0,0 +1,58 @@
+From 7c06d1fd27c157bde43bc5830523406075b292e6 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:42 +0300
+Subject: [PATCH] vmstate: fix buffer overflow in target-arm/machine.c
+
+CVE-2013-4531
+
+cpreg_vmstate_indexes is a VARRAY_INT32. A negative value for
+cpreg_vmstate_array_len will cause a buffer overflow.
+
+VMSTATE_INT32_LE was supposed to protect against this
+but doesn't because it doesn't validate that input is
+non-negative.
+
+Fix this macro to valide the value appropriately.
+
+The only other user of VMSTATE_INT32_LE doesn't
+ever use negative numbers so it doesn't care.
+
+Reported-by: Anthony Liguori <anthony at codemonkey.ws>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit d2ef4b61fe6d33d2a5dcf100a9b9440de341ad62)
+---
+ savevm.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/savevm.c b/savevm.c
+index 9f7f668..ffc1a7c 100644
+--- a/savevm.c
++++ b/savevm.c
+@@ -1104,17 +1104,20 @@ const VMStateInfo vmstate_info_int32_equal = {
+     .put  = put_int32,
+ };
+ 
+-/* 32 bit int. See that the received value is the less or the same
+-   than the one in the field */
++/* 32 bit int. Check that the received value is non-negative
++ * and less than or equal to the one in the field.
++ */
+ 
+ static int get_int32_le(QEMUFile *f, void *pv, size_t size)
+ {
+-    int32_t *old = pv;
+-    int32_t new;
+-    qemu_get_sbe32s(f, &new);
++    int32_t *cur = pv;
++    int32_t loaded;
++    qemu_get_sbe32s(f, &loaded);
+ 
+-    if (*old <= new)
++    if (loaded >= 0 && loaded <= *cur) {
++        *cur = loaded;
+         return 0;
++    }
+     return -EINVAL;
+ }
+ 
diff --git a/0311-virtio-avoid-buffer-overrun-on-incoming-migration.patch b/0311-virtio-avoid-buffer-overrun-on-incoming-migration.patch
new file mode 100644
index 0000000..20bdfdd
--- /dev/null
+++ b/0311-virtio-avoid-buffer-overrun-on-incoming-migration.patch
@@ -0,0 +1,40 @@
+From 13d99f8f2fc86490456a7d96d58a84bc22da025f Mon Sep 17 00:00:00 2001
+From: Michael Roth <mdroth at linux.vnet.ibm.com>
+Date: Thu, 3 Apr 2014 19:51:46 +0300
+Subject: [PATCH] virtio: avoid buffer overrun on incoming migration
+
+CVE-2013-6399
+
+vdev->queue_sel is read from the wire, and later used in the
+emulation code as an index into vdev->vq[]. If the value of
+vdev->queue_sel exceeds the length of vdev->vq[], currently
+allocated to be VIRTIO_PCI_QUEUE_MAX elements, subsequent PIO
+operations such as VIRTIO_PCI_QUEUE_PFN can be used to overrun
+the buffer with arbitrary data originating from the source.
+
+Fix this by failing migration if the value from the wire exceeds
+VIRTIO_PCI_QUEUE_MAX.
+
+Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 4b53c2c72cb5541cf394033b528a6fe2a86c0ac1)
+---
+ hw/virtio/virtio.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 8dc3cb3..705fad9 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -904,6 +904,9 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
+     qemu_get_8s(f, &vdev->status);
+     qemu_get_8s(f, &vdev->isr);
+     qemu_get_be16s(f, &vdev->queue_sel);
++    if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {
++        return -1;
++    }
+     qemu_get_be32s(f, &features);
+ 
+     if (virtio_set_features(vdev, features) < 0) {
diff --git a/0312-virtio-validate-num_sg-when-mapping.patch b/0312-virtio-validate-num_sg-when-mapping.patch
new file mode 100644
index 0000000..031c02e
--- /dev/null
+++ b/0312-virtio-validate-num_sg-when-mapping.patch
@@ -0,0 +1,41 @@
+From 96833882a177a049a9ece3bb00dffd7c5395a7d7 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:53 +0300
+Subject: [PATCH] virtio: validate num_sg when mapping
+
+CVE-2013-4535
+CVE-2013-4536
+
+Both virtio-block and virtio-serial read,
+VirtQueueElements are read in as buffers, and passed to
+virtqueue_map_sg(), where num_sg is taken from the wire and can force
+writes to indicies beyond VIRTQUEUE_MAX_SIZE.
+
+To fix, validate num_sg.
+
+Reported-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Cc: Amit Shah <amit.shah at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 36cf2a37132c7f01fa9adb5f95f5312b27742fd4)
+---
+ hw/virtio/virtio.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index 705fad9..c2c9b5a 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -427,6 +427,12 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
+     unsigned int i;
+     hwaddr len;
+ 
++    if (num_sg >= VIRTQUEUE_MAX_SIZE) {
++        error_report("virtio: map attempt out of bounds: %zd > %d",
++                     num_sg, VIRTQUEUE_MAX_SIZE);
++        exit(1);
++    }
++
+     for (i = 0; i < num_sg; i++) {
+         len = sg[i].iov_len;
+         sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
diff --git a/0313-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch b/0313-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch
new file mode 100644
index 0000000..a7e82e7
--- /dev/null
+++ b/0313-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch
@@ -0,0 +1,51 @@
+From 49611d4f865665307de64d7736e59b9ca33f4861 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:51:57 +0300
+Subject: [PATCH] pxa2xx: avoid buffer overrun on incoming migration
+
+CVE-2013-4533
+
+s->rx_level is read from the wire and used to determine how many bytes
+to subsequently read into s->rx_fifo[]. If s->rx_level exceeds the
+length of s->rx_fifo[] the buffer can be overrun with arbitrary data
+from the wire.
+
+Fix this by validating rx_level against the size of s->rx_fifo.
+
+Cc: Don Koch <dkoch at verizon.com>
+Reported-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
+Reviewed-by: Don Koch <dkoch at verizon.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit caa881abe0e01f9931125a0977ec33c5343e4aa7)
+---
+ hw/arm/pxa2xx.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
+index 17ddd3f..f916185 100644
+--- a/hw/arm/pxa2xx.c
++++ b/hw/arm/pxa2xx.c
+@@ -742,7 +742,7 @@ static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
+ static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
+ {
+     PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+-    int i;
++    int i, v;
+ 
+     s->enable = qemu_get_be32(f);
+ 
+@@ -756,7 +756,11 @@ static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
+     qemu_get_8s(f, &s->ssrsa);
+     qemu_get_8s(f, &s->ssacd);
+ 
+-    s->rx_level = qemu_get_byte(f);
++    v = qemu_get_byte(f);
++    if (v < 0 || v > ARRAY_SIZE(s->rx_fifo)) {
++        return -EINVAL;
++    }
++    s->rx_level = v;
+     s->rx_start = 0;
+     for (i = 0; i < s->rx_level; i ++)
+         s->rx_fifo[i] = qemu_get_byte(f);
diff --git a/0314-ssd0323-fix-buffer-overun-on-invalid-state-load.patch b/0314-ssd0323-fix-buffer-overun-on-invalid-state-load.patch
new file mode 100644
index 0000000..984b5dc
--- /dev/null
+++ b/0314-ssd0323-fix-buffer-overun-on-invalid-state-load.patch
@@ -0,0 +1,77 @@
+From 6a12145ab4edb57b88f7eb51ffa472dc29aa428e Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:52:05 +0300
+Subject: [PATCH] ssd0323: fix buffer overun on invalid state load
+
+CVE-2013-4538
+
+s->cmd_len used as index in ssd0323_transfer() to store 32-bit field.
+Possible this field might then be supplied by guest to overwrite a
+return addr somewhere. Same for row/col fields, which are indicies into
+framebuffer array.
+
+To fix validate after load.
+
+Additionally, validate that the row/col_start/end are within bounds;
+otherwise the guest can provoke an overrun by either setting the _end
+field so large that the row++ increments just walk off the end of the
+array, or by setting the _start value to something bogus and then
+letting the "we hit end of row" logic reset row to row_start.
+
+For completeness, validate mode as well.
+
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit ead7a57df37d2187813a121308213f41591bd811)
+---
+ hw/display/ssd0323.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
+index c3231c6..773414c 100644
+--- a/hw/display/ssd0323.c
++++ b/hw/display/ssd0323.c
+@@ -312,18 +312,42 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
+         return -EINVAL;
+ 
+     s->cmd_len = qemu_get_be32(f);
++    if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
++        return -EINVAL;
++    }
+     s->cmd = qemu_get_be32(f);
+     for (i = 0; i < 8; i++)
+         s->cmd_data[i] = qemu_get_be32(f);
+     s->row = qemu_get_be32(f);
++    if (s->row < 0 || s->row >= 80) {
++        return -EINVAL;
++    }
+     s->row_start = qemu_get_be32(f);
++    if (s->row_start < 0 || s->row_start >= 80) {
++        return -EINVAL;
++    }
+     s->row_end = qemu_get_be32(f);
++    if (s->row_end < 0 || s->row_end >= 80) {
++        return -EINVAL;
++    }
+     s->col = qemu_get_be32(f);
++    if (s->col < 0 || s->col >= 64) {
++        return -EINVAL;
++    }
+     s->col_start = qemu_get_be32(f);
++    if (s->col_start < 0 || s->col_start >= 64) {
++        return -EINVAL;
++    }
+     s->col_end = qemu_get_be32(f);
++    if (s->col_end < 0 || s->col_end >= 64) {
++        return -EINVAL;
++    }
+     s->redraw = qemu_get_be32(f);
+     s->remap = qemu_get_be32(f);
+     s->mode = qemu_get_be32(f);
++    if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
++        return -EINVAL;
++    }
+     qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
+ 
+     ss->cs = qemu_get_be32(f);
diff --git a/0315-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch b/0315-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch
new file mode 100644
index 0000000..5cff04b
--- /dev/null
+++ b/0315-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch
@@ -0,0 +1,50 @@
+From ae581d63688050741eb913e238189d5dc04efa93 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:52:09 +0300
+Subject: [PATCH] tsc210x: fix buffer overrun on invalid state load
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+CVE-2013-4539
+
+s->precision, nextprecision, function and nextfunction
+come from wire and are used
+as idx into resolution[] in TSC_CUT_RESOLUTION.
+
+Validate after load to avoid buffer overrun.
+
+Cc: Andreas Färber <afaerber at suse.de>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 5193be3be35f29a35bc465036cd64ad60d43385f)
+---
+ hw/input/tsc210x.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
+index 9b854e7..6ba110b 100644
+--- a/hw/input/tsc210x.c
++++ b/hw/input/tsc210x.c
+@@ -1070,9 +1070,21 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
+     s->enabled = qemu_get_byte(f);
+     s->host_mode = qemu_get_byte(f);
+     s->function = qemu_get_byte(f);
++    if (s->function < 0 || s->function >= ARRAY_SIZE(mode_regs)) {
++        return -EINVAL;
++    }
+     s->nextfunction = qemu_get_byte(f);
++    if (s->nextfunction < 0 || s->nextfunction >= ARRAY_SIZE(mode_regs)) {
++        return -EINVAL;
++    }
+     s->precision = qemu_get_byte(f);
++    if (s->precision < 0 || s->precision >= ARRAY_SIZE(resolution)) {
++        return -EINVAL;
++    }
+     s->nextprecision = qemu_get_byte(f);
++    if (s->nextprecision < 0 || s->nextprecision >= ARRAY_SIZE(resolution)) {
++        return -EINVAL;
++    }
+     s->filter = qemu_get_byte(f);
+     s->pin_func = qemu_get_byte(f);
+     s->ref = qemu_get_byte(f);
diff --git a/0316-zaurus-fix-buffer-overrun-on-invalid-state-load.patch b/0316-zaurus-fix-buffer-overrun-on-invalid-state-load.patch
new file mode 100644
index 0000000..4edac72
--- /dev/null
+++ b/0316-zaurus-fix-buffer-overrun-on-invalid-state-load.patch
@@ -0,0 +1,54 @@
+From 59840bc9eafc380ff16f9b190428297da2c228ee Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:52:13 +0300
+Subject: [PATCH] zaurus: fix buffer overrun on invalid state load
+
+CVE-2013-4540
+
+Within scoop_gpio_handler_update, if prev_level has a high bit set, then
+we get bit > 16 and that causes a buffer overrun.
+
+Since prev_level comes from wire indirectly, this can
+happen on invalid state load.
+
+Similarly for gpio_level and gpio_dir.
+
+To fix, limit to 16 bit.
+
+Reported-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Dr. David Alan Gilbert <dgilbert at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 52f91c3723932f8340fe36c8ec8b18a757c37b2b)
+---
+ hw/gpio/zaurus.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
+index dc79a8b..8e2ce04 100644
+--- a/hw/gpio/zaurus.c
++++ b/hw/gpio/zaurus.c
+@@ -203,6 +203,15 @@ static bool is_version_0 (void *opaque, int version_id)
+     return version_id == 0;
+ }
+ 
++static bool vmstate_scoop_validate(void *opaque, int version_id)
++{
++    ScoopInfo *s = opaque;
++
++    return !(s->prev_level & 0xffff0000) &&
++        !(s->gpio_level & 0xffff0000) &&
++        !(s->gpio_dir & 0xffff0000);
++}
++
+ static const VMStateDescription vmstate_scoop_regs = {
+     .name = "scoop",
+     .version_id = 1,
+@@ -215,6 +224,7 @@ static const VMStateDescription vmstate_scoop_regs = {
+         VMSTATE_UINT32(gpio_level, ScoopInfo),
+         VMSTATE_UINT32(gpio_dir, ScoopInfo),
+         VMSTATE_UINT32(prev_level, ScoopInfo),
++        VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
+         VMSTATE_UINT16(mcr, ScoopInfo),
+         VMSTATE_UINT16(cdr, ScoopInfo),
+         VMSTATE_UINT16(ccr, ScoopInfo),
diff --git a/0317-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch b/0317-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch
new file mode 100644
index 0000000..f02f1f2
--- /dev/null
+++ b/0317-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch
@@ -0,0 +1,67 @@
+From 8f3ff5dded47e3c40a8f72115f510ab06988480e Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:52:17 +0300
+Subject: [PATCH] virtio-scsi: fix buffer overrun on invalid state load
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+CVE-2013-4542
+
+hw/scsi/scsi-bus.c invokes load_request.
+
+ virtio_scsi_load_request does:
+    qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
+
+this probably can make elem invalid, for example,
+make in_num or out_num huge, then:
+
+    virtio_scsi_parse_req(s, vs->cmd_vqs[n], req);
+
+will do:
+
+    if (req->elem.out_num > 1) {
+        qemu_sgl_init_external(req, &req->elem.out_sg[1],
+                               &req->elem.out_addr[1],
+                               req->elem.out_num - 1);
+    } else {
+        qemu_sgl_init_external(req, &req->elem.in_sg[1],
+                               &req->elem.in_addr[1],
+                               req->elem.in_num - 1);
+    }
+
+and this will access out of array bounds.
+
+Note: this adds security checks within assert calls since
+SCSIBusInfo's load_request cannot fail.
+For now simply disable builds with NDEBUG - there seems
+to be little value in supporting these.
+
+Cc: Andreas Färber <afaerber at suse.de>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 3c3ce981423e0d6c18af82ee62f1850c2cda5976)
+---
+ hw/scsi/virtio-scsi.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
+index 15e40d9..8ab72ae 100644
+--- a/hw/scsi/virtio-scsi.c
++++ b/hw/scsi/virtio-scsi.c
+@@ -147,6 +147,15 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
+     qemu_get_be32s(f, &n);
+     assert(n < vs->conf.num_queues);
+     qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
++    /* TODO: add a way for SCSIBusInfo's load_request to fail,
++     * and fail migration instead of asserting here.
++     * When we do, we might be able to re-enable NDEBUG below.
++     */
++#ifdef NDEBUG
++#error building with NDEBUG is not supported
++#endif
++    assert(req->elem.in_num <= ARRAY_SIZE(req->elem.in_sg));
++    assert(req->elem.out_num <= ARRAY_SIZE(req->elem.out_sg));
+     virtio_scsi_parse_req(s, vs->cmd_vqs[n], req);
+ 
+     scsi_req_ref(sreq);
diff --git a/0318-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch b/0318-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch
new file mode 100644
index 0000000..5c43c9a
--- /dev/null
+++ b/0318-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch
@@ -0,0 +1,65 @@
+From 5995fff2797fbe4cf9517f724ecddd79028bc0a9 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:52:21 +0300
+Subject: [PATCH] vmstate: s/VMSTATE_INT32_LE/VMSTATE_INT32_POSITIVE_LE/
+
+As the macro verifies the value is positive, rename it
+to make the function clearer.
+
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 3476436a44c29725efef0cabf5b3ea4e70054d57)
+---
+ hw/pci/pci.c                | 4 ++--
+ include/migration/vmstate.h | 2 +-
+ target-arm/machine.c        | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/hw/pci/pci.c b/hw/pci/pci.c
+index 129cdb7..0f1d167 100644
+--- a/hw/pci/pci.c
++++ b/hw/pci/pci.c
+@@ -471,7 +471,7 @@ const VMStateDescription vmstate_pci_device = {
+     .minimum_version_id = 1,
+     .minimum_version_id_old = 1,
+     .fields      = (VMStateField []) {
+-        VMSTATE_INT32_LE(version_id, PCIDevice),
++        VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
+         VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
+                                    vmstate_info_pci_config,
+                                    PCI_CONFIG_SPACE_SIZE),
+@@ -488,7 +488,7 @@ const VMStateDescription vmstate_pcie_device = {
+     .minimum_version_id = 1,
+     .minimum_version_id_old = 1,
+     .fields      = (VMStateField []) {
+-        VMSTATE_INT32_LE(version_id, PCIDevice),
++        VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
+         VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
+                                    vmstate_info_pci_config,
+                                    PCIE_CONFIG_SPACE_SIZE),
+diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
+index d5a63ce..7ffb7cd 100644
+--- a/include/migration/vmstate.h
++++ b/include/migration/vmstate.h
+@@ -578,7 +578,7 @@ extern const VMStateInfo vmstate_info_bitmap;
+ #define VMSTATE_UINT64_EQUAL(_f, _s)                                  \
+     VMSTATE_UINT64_EQUAL_V(_f, _s, 0)
+ 
+-#define VMSTATE_INT32_LE(_f, _s)                                   \
++#define VMSTATE_INT32_POSITIVE_LE(_f, _s)                             \
+     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
+ 
+ #define VMSTATE_UINT8_TEST(_f, _s, _t)                               \
+diff --git a/target-arm/machine.c b/target-arm/machine.c
+index 6d4c2d4..f3041af 100644
+--- a/target-arm/machine.c
++++ b/target-arm/machine.c
+@@ -246,7 +246,7 @@ const VMStateDescription vmstate_arm_cpu = {
+         /* The length-check must come before the arrays to avoid
+          * incoming data possibly overflowing the array.
+          */
+-        VMSTATE_INT32_LE(cpreg_vmstate_array_len, ARMCPU),
++        VMSTATE_INT32_POSITIVE_LE(cpreg_vmstate_array_len, ARMCPU),
+         VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU,
+                              cpreg_vmstate_array_len,
+                              0, vmstate_info_uint64, uint64_t),
diff --git a/0319-usb-sanity-check-setup_index-setup_len-in-post_load.patch b/0319-usb-sanity-check-setup_index-setup_len-in-post_load.patch
new file mode 100644
index 0000000..18aa405
--- /dev/null
+++ b/0319-usb-sanity-check-setup_index-setup_len-in-post_load.patch
@@ -0,0 +1,40 @@
+From 40ad1e24578d5c8d09d06533c68f824e46eddae3 Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Thu, 3 Apr 2014 19:52:25 +0300
+Subject: [PATCH] usb: sanity check setup_index+setup_len in post_load
+
+CVE-2013-4541
+
+s->setup_len and s->setup_index are fed into usb_packet_copy as
+size/offset into s->data_buf, it's possible for invalid state to exploit
+this to load arbitrary data.
+
+setup_len and setup_index should be checked to make sure
+they are not negative.
+
+Cc: Gerd Hoffmann <kraxel at redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Reviewed-by: Gerd Hoffmann <kraxel at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 9f8e9895c504149d7048e9fc5eb5cbb34b16e49a)
+---
+ hw/usb/bus.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/hw/usb/bus.c b/hw/usb/bus.c
+index f83d1de..c6c2005 100644
+--- a/hw/usb/bus.c
++++ b/hw/usb/bus.c
+@@ -47,6 +47,12 @@ static int usb_device_post_load(void *opaque, int version_id)
+     } else {
+         dev->attached = 1;
+     }
++    if (dev->setup_index < 0 ||
++        dev->setup_len < 0 ||
++        dev->setup_index >= sizeof(dev->data_buf) ||
++        dev->setup_len >= sizeof(dev->data_buf)) {
++        return -EINVAL;
++    }
+     return 0;
+ }
+ 
diff --git a/0320-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch b/0320-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch
new file mode 100644
index 0000000..3496bcb
--- /dev/null
+++ b/0320-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch
@@ -0,0 +1,41 @@
+From cdf7756e2d33a9bb71df592037d11ad78333cdfa Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Mon, 28 Apr 2014 16:08:14 +0300
+Subject: [PATCH] ssi-sd: fix buffer overrun on invalid state load
+
+CVE-2013-4537
+
+s->arglen is taken from wire and used as idx
+in ssi_sd_transfer().
+
+Validate it before access.
+
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit a9c380db3b8c6af19546a68145c8d1438a09c92b)
+---
+ hw/sd/ssi-sd.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
+index d47e237..6a21f95 100644
+--- a/hw/sd/ssi-sd.c
++++ b/hw/sd/ssi-sd.c
+@@ -230,8 +230,17 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
+     for (i = 0; i < 5; i++)
+         s->response[i] = qemu_get_be32(f);
+     s->arglen = qemu_get_be32(f);
++    if (s->mode == SSI_SD_CMDARG &&
++        (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
++        return -EINVAL;
++    }
+     s->response_pos = qemu_get_be32(f);
+     s->stopping = qemu_get_be32(f);
++    if (s->mode == SSI_SD_RESPONSE &&
++        (s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
++        (!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
++        return -EINVAL;
++    }
+ 
+     ss->cs = qemu_get_be32(f);
+ 
diff --git a/0321-openpic-avoid-buffer-overrun-on-incoming-migration.patch b/0321-openpic-avoid-buffer-overrun-on-incoming-migration.patch
new file mode 100644
index 0000000..a00125f
--- /dev/null
+++ b/0321-openpic-avoid-buffer-overrun-on-incoming-migration.patch
@@ -0,0 +1,72 @@
+From c8621a80f8b8f3cfffddea4a2c30e30b59cdc7e6 Mon Sep 17 00:00:00 2001
+From: Michael Roth <mdroth at linux.vnet.ibm.com>
+Date: Mon, 28 Apr 2014 16:08:17 +0300
+Subject: [PATCH] openpic: avoid buffer overrun on incoming migration
+
+CVE-2013-4534
+
+opp->nb_cpus is read from the wire and used to determine how many
+IRQDest elements to read into opp->dst[]. If the value exceeds the
+length of opp->dst[], MAX_CPU, opp->dst[] can be overrun with arbitrary
+data from the wire.
+
+Fix this by failing migration if the value read from the wire exceeds
+MAX_CPU.
+
+Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Reviewed-by: Alexander Graf <agraf at suse.de>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 73d963c0a75cb99c6aaa3f6f25e427aa0b35a02e)
+---
+ hw/intc/openpic.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
+index 7df72f4..ede1bc4 100644
+--- a/hw/intc/openpic.c
++++ b/hw/intc/openpic.c
+@@ -41,6 +41,7 @@
+ #include "hw/sysbus.h"
+ #include "hw/pci/msi.h"
+ #include "qemu/bitops.h"
++#include "qapi/qmp/qerror.h"
+ 
+ //#define DEBUG_OPENPIC
+ 
+@@ -1416,7 +1417,7 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
+ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
+ {
+     OpenPICState *opp = (OpenPICState *)opaque;
+-    unsigned int i;
++    unsigned int i, nb_cpus;
+ 
+     if (version_id != 1) {
+         return -EINVAL;
+@@ -1428,7 +1429,11 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
+     qemu_get_be32s(f, &opp->spve);
+     qemu_get_be32s(f, &opp->tfrr);
+ 
+-    qemu_get_be32s(f, &opp->nb_cpus);
++    qemu_get_be32s(f, &nb_cpus);
++    if (opp->nb_cpus != nb_cpus) {
++        return -EINVAL;
++    }
++    assert(nb_cpus > 0 && nb_cpus <= MAX_CPU);
+ 
+     for (i = 0; i < opp->nb_cpus; i++) {
+         qemu_get_sbe32s(f, &opp->dst[i].ctpr);
+@@ -1567,6 +1572,13 @@ static void openpic_realize(DeviceState *dev, Error **errp)
+         {NULL}
+     };
+ 
++    if (opp->nb_cpus > MAX_CPU) {
++        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
++                  TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
++                  (uint64_t)0, (uint64_t)MAX_CPU);
++        return;
++    }
++
+     switch (opp->model) {
+     case OPENPIC_MODEL_FSL_MPIC_20:
+     default:
diff --git a/0322-virtio-net-out-of-bounds-buffer-write-on-load.patch b/0322-virtio-net-out-of-bounds-buffer-write-on-load.patch
new file mode 100644
index 0000000..9643a6a
--- /dev/null
+++ b/0322-virtio-net-out-of-bounds-buffer-write-on-load.patch
@@ -0,0 +1,55 @@
+From 4319e783e7d9cb6ca10a353e00047b2f8240065a Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Mon, 28 Apr 2014 16:08:21 +0300
+Subject: [PATCH] virtio-net: out-of-bounds buffer write on load
+
+CVE-2013-4149 QEMU 1.3.0 out-of-bounds buffer write in
+virtio_net_load()@hw/net/virtio-net.c
+
+>         } else if (n->mac_table.in_use) {
+>             uint8_t *buf = g_malloc0(n->mac_table.in_use);
+
+We are allocating buffer of size n->mac_table.in_use
+
+>             qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);
+
+and read to the n->mac_table.in_use size buffer n->mac_table.in_use *
+ETH_ALEN bytes, corrupting memory.
+
+If adversary controls state then memory written there is controlled
+by adversary.
+
+Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit 98f93ddd84800f207889491e0b5d851386b459cf)
+---
+ hw/net/virtio-net.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
+index 5907e96..8064092 100644
+--- a/hw/net/virtio-net.c
++++ b/hw/net/virtio-net.c
+@@ -1334,10 +1334,17 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
+         if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
+             qemu_get_buffer(f, n->mac_table.macs,
+                             n->mac_table.in_use * ETH_ALEN);
+-        } else if (n->mac_table.in_use) {
+-            uint8_t *buf = g_malloc0(n->mac_table.in_use);
+-            qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);
+-            g_free(buf);
++        } else {
++            int64_t i;
++
++            /* Overflow detected - can happen if source has a larger MAC table.
++             * We simply set overflow flag so there's no need to maintain the
++             * table of addresses, discard them all.
++             * Note: 64 bit math to avoid integer overflow.
++             */
++            for (i = 0; i < (int64_t)n->mac_table.in_use * ETH_ALEN; ++i) {
++                qemu_get_byte(f);
++            }
+             n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
+             n->mac_table.in_use = 0;
+         }
diff --git a/0323-virtio-validate-config_len-on-load.patch b/0323-virtio-validate-config_len-on-load.patch
new file mode 100644
index 0000000..c923c6c
--- /dev/null
+++ b/0323-virtio-validate-config_len-on-load.patch
@@ -0,0 +1,52 @@
+From 78f8c6d925afb6a125bad5a8901e55b5d3859dfc Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Mon, 28 Apr 2014 16:08:23 +0300
+Subject: [PATCH] virtio: validate config_len on load
+
+Malformed input can have config_len in migration stream
+exceed the array size allocated on destination, the
+result will be heap overflow.
+
+To fix, that config_len matches on both sides.
+
+CVE-2014-0182
+
+Reported-by: "Dr. David Alan Gilbert" <dgilbert at redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+
+--
+
+v2: use %ix and %zx to print config_len values
+Signed-off-by: Juan Quintela <quintela at redhat.com>
+(cherry picked from commit a890a2f9137ac3cf5b607649e66a6f3a5512d8dc)
+---
+ hw/virtio/virtio.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
+index c2c9b5a..151fae9 100644
+--- a/hw/virtio/virtio.c
++++ b/hw/virtio/virtio.c
+@@ -895,6 +895,7 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val)
+ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
+ {
+     int i, ret;
++    int32_t config_len;
+     uint32_t num;
+     uint32_t features;
+     uint32_t supported_features;
+@@ -921,7 +922,12 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
+                      features, supported_features);
+         return -1;
+     }
+-    vdev->config_len = qemu_get_be32(f);
++    config_len = qemu_get_be32(f);
++    if (config_len != vdev->config_len) {
++        error_report("Unexpected config length 0x%x. Expected 0x%zx",
++                     config_len, vdev->config_len);
++        return -1;
++    }
+     qemu_get_buffer(f, vdev->config, vdev->config_len);
+ 
+     num = qemu_get_be32(f);
diff --git a/qemu.spec b/qemu.spec
index 93e0701..cd68619 100644
--- a/qemu.spec
+++ b/qemu.spec
@@ -139,7 +139,7 @@
 Summary: QEMU is a FAST! processor emulator
 Name: qemu
 Version: 1.6.2
-Release: 4%{?dist}
+Release: 5%{?dist}
 Epoch: 2
 License: GPLv2+ and LGPLv2+ and BSD
 Group: Development/Tools
@@ -312,6 +312,31 @@ Patch0217: 0217-arm_gic-Support-setting-getting-binary-point-reg.patch
 Patch0218: 0218-arm_gic-Add-GICC_APRn-state-to-the-GICState.patch
 Patch0219: 0219-hw-intc-arm_gic-Fix-NVIC-assertion-failure.patch
 
+# Migration CVEs: CVE-2014-0182 etc.
+Patch0301: 0301-vmstate-add-VMS_MUST_EXIST.patch
+Patch0302: 0302-vmstate-add-VMSTATE_VALIDATE.patch
+Patch0303: 0303-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch
+Patch0304: 0304-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch
+Patch0305: 0305-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch
+Patch0306: 0306-ahci-fix-buffer-overrun-on-invalid-state-load.patch
+Patch0307: 0307-hpet-fix-buffer-overrun-on-invalid-state-load.patch
+Patch0308: 0308-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch
+Patch0309: 0309-pl022-fix-buffer-overun-on-invalid-state-load.patch
+Patch0310: 0310-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch
+Patch0311: 0311-virtio-avoid-buffer-overrun-on-incoming-migration.patch
+Patch0312: 0312-virtio-validate-num_sg-when-mapping.patch
+Patch0313: 0313-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch
+Patch0314: 0314-ssd0323-fix-buffer-overun-on-invalid-state-load.patch
+Patch0315: 0315-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch
+Patch0316: 0316-zaurus-fix-buffer-overrun-on-invalid-state-load.patch
+Patch0317: 0317-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch
+Patch0318: 0318-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch
+Patch0319: 0319-usb-sanity-check-setup_index-setup_len-in-post_load.patch
+Patch0320: 0320-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch
+Patch0321: 0321-openpic-avoid-buffer-overrun-on-incoming-migration.patch
+Patch0322: 0322-virtio-net-out-of-bounds-buffer-write-on-load.patch
+Patch0323: 0323-virtio-validate-config_len-on-load.patch
+
 BuildRequires: SDL-devel
 BuildRequires: zlib-devel
 BuildRequires: which
@@ -955,6 +980,31 @@ CAC emulation development files.
 %patch0218 -p1
 %patch0219 -p1
 
+# Migration CVEs: CVE-2014-0182 etc.
+%patch0301 -p1
+%patch0302 -p1
+%patch0303 -p1
+%patch0304 -p1
+%patch0305 -p1
+%patch0306 -p1
+%patch0307 -p1
+%patch0308 -p1
+%patch0309 -p1
+%patch0310 -p1
+%patch0311 -p1
+%patch0312 -p1
+%patch0313 -p1
+%patch0314 -p1
+%patch0315 -p1
+%patch0316 -p1
+%patch0317 -p1
+%patch0318 -p1
+%patch0319 -p1
+%patch0320 -p1
+%patch0321 -p1
+%patch0322 -p1
+%patch0323 -p1
+
 
 %build
 %if %{with kvmonly}
@@ -1661,6 +1711,9 @@ getent passwd qemu >/dev/null || \
 %endif
 
 %changelog
+* Sun May 11 2014 Cole Robinson <crobinso at redhat.com> - 2:1.6.2-5
+- Migration CVEs: CVE-2014-0182 etc.
+
 * Tue Apr 29 2014 Cole Robinson <crobinso at redhat.com> - 2:1.6.2-4
 - Fix arm sd warnings with latest kernel (bz #1091548)
 - Fix regression in CVE backport that affects openstack (thanks lbezdick)


More information about the scm-commits mailing list