Migration CVEs: CVE-2014-0182 etc.

This commit is contained in:
Cole Robinson 2014-05-11 19:07:44 -04:00
parent 5461c5246c
commit 70114f9e56
25 changed files with 1256 additions and 2 deletions

View File

@ -1,4 +1,4 @@
From 6b4fcd4bb73c86c7754bcc912a557ba62180ae0b Mon Sep 17 00:00:00 2001
From 9d8e4e500dca987531be3666422f17c9486940b2 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Wed, 19 Mar 2014 14:57:27 -0400
Subject: [PATCH] Change gtk quit accelerator to ctrl+shift+q (bz 1062393)

View File

@ -0,0 +1,57 @@
From 105071cc70a454680e6bf11e2d9d7b73c7ce7491 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 5bf81c8d63db0216a4d29dc87f9ce530bb791dd1)
---
include/migration/vmstate.h | 1 +
vmstate.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index e7e1705..de970ab 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/vmstate.c b/vmstate.c
index b689f2f..d856319 100644
--- a/vmstate.c
+++ b/vmstate.c
@@ -78,6 +78,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++;
}
@@ -138,6 +142,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++;
}

View File

@ -0,0 +1,33 @@
From d9e0cb134eefe5104b404b91eaf969a2cd74bd9f Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 de970ab..5b71370 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), \

View File

@ -0,0 +1,59 @@
From ea96c6a9c91da1923aa922a781fd7abbf9f51b6c Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Juan Quintela <quintela@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;

View File

@ -0,0 +1,55 @@
From 9229c44bfa3549085ac68265d9be95a8552c4fa4 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Juan Quintela <quintela@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 33bd233..0a8cb40 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1407,6 +1407,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);
}

View File

@ -0,0 +1,52 @@
From 23f0db5c309893195025bc75402f3f9e1b4de743 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@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@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Juan Quintela <quintela@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 aeabf3a..05f05e7 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -891,7 +891,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));
@@ -919,6 +920,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) {

View File

@ -0,0 +1,36 @@
From 95fa012ed61e1e8b88d701b8f75b38dc5edb16e2 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Juan Quintela <quintela@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 bfe633f..457a7a1 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1293,7 +1293,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()
},
};

View File

@ -0,0 +1,51 @@
From 5e0e0a12887c9e70356c23d20b08b08eabd4a6df Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 e15d6bc..2792f89 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -239,6 +239,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;
@@ -307,6 +319,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()

View File

@ -0,0 +1,55 @@
From b6f53085cc618bc7e58be702afacad1b5dcae5ba Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@codemonkey.ws>
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 991502e..535be2c 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()

View File

@ -0,0 +1,50 @@
From 872fc04ecd90e0ca4d8ac4565b3a9f246c070873 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com
Reported-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@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),

View File

@ -0,0 +1,52 @@
From acf45756e165664f6d70025c02ddca563adee496 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@codemonkey.ws>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit d2ef4b61fe6d33d2a5dcf100a9b9440de341ad62)
---
vmstate.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/vmstate.c b/vmstate.c
index d856319..105f184 100644
--- a/vmstate.c
+++ b/vmstate.c
@@ -333,8 +333,9 @@ const VMStateInfo vmstate_info_int32_equal = {
.put = put_int32,
};
-/* 32 bit int. Check that the received value is less than or equal to
- 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)
{
@@ -342,7 +343,7 @@ static int get_int32_le(QEMUFile *f, void *pv, size_t size)
int32_t loaded;
qemu_get_sbe32s(f, &loaded);
- if (loaded <= *cur) {
+ if (loaded >= 0 && loaded <= *cur) {
*cur = loaded;
return 0;
}

View File

@ -0,0 +1,40 @@
From 9b5cc034e1ed5b2ebc133029d4f865f186c6b895 Mon Sep 17 00:00:00 2001
From: Michael Roth <mdroth@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@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Juan Quintela <quintela@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 05f05e7..0072542 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -907,6 +907,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) {

View File

@ -0,0 +1,41 @@
From f1344659fd93ea0dfb9d8d1af25993e57584c773 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Cc: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 0072542..a70169a 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -430,6 +430,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);

View File

@ -0,0 +1,51 @@
From 43b30dec4d07aa81ff5f2dc3b0a064fa589fd3af Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@verizon.com>
Reported-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Don Koch <dkoch@verizon.com>
Signed-off-by: Juan Quintela <quintela@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 0429148..e0cd847 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -732,7 +732,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);
@@ -746,7 +746,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);

View File

@ -0,0 +1,77 @@
From 0cbd8c5754d6f56b53717e92353772777a799b87 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Juan Quintela <quintela@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 971152e..9727007 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);

View File

@ -0,0 +1,50 @@
From 984fcc9ad2abc4429422c045d68e17f1eb1fa4b2 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@suse.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 485c9e5..aa5b688 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);

View File

@ -0,0 +1,54 @@
From 985b046012f258fd5a2164fb85e9d792f574697c Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@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),

View File

@ -0,0 +1,67 @@
From 579bb2000dbcd8a415660e76d31f521d87ac1302 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@suse.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 b0d7517..1752193 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);

View File

@ -0,0 +1,65 @@
From 83bb87c00e9970a1771ddcad3fd99091f5b2719c Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 2a9f08e..517ff2a 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -475,7 +475,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),
@@ -492,7 +492,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 5b71370..7e45048 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -601,7 +601,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 7ced87a..5746ffd 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),

View File

@ -0,0 +1,38 @@
From a608c9c4150820ec64f5f25f6ebe244906c015da Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 9f8e9895c504149d7048e9fc5eb5cbb34b16e49a)
---
hw/usb/bus.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index fe70429..e48b19f 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -49,7 +49,9 @@ static int usb_device_post_load(void *opaque, int version_id)
} else {
dev->attached = 1;
}
- if (dev->setup_index >= sizeof(dev->data_buf) ||
+ 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;
}

View File

@ -0,0 +1,41 @@
From d2c50b94a808f06d778746aec63ce2cb4eb1222f Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 3273c8a..b012e57 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);

View File

@ -0,0 +1,72 @@
From 70488d5f1746b720bc141ea6b9850585e9c42121 Mon Sep 17 00:00:00 2001
From: Michael Roth <mdroth@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@linux.vnet.ibm.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 be76fbd..17136c9 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:

View File

@ -0,0 +1,55 @@
From 1a29e58f9f23846d0e105a3157629786fc624f65 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@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 0a8cb40..940a7cf 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1362,10 +1362,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;
}

View File

@ -0,0 +1,52 @@
From 94998eaa5ef06ba17ad12976ac84801033a28582 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@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@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
--
v2: use %ix and %zx to print config_len values
Signed-off-by: Juan Quintela <quintela@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 a70169a..7f4e7ec 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -898,6 +898,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;
@@ -924,7 +925,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);

View File

@ -158,7 +158,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 2.0.0
Release: 3%{?dist}
Release: 4%{?dist}
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
Group: Development/Tools
@ -201,6 +201,30 @@ Source13: qemu-kvm.sh
# Change gtk quit accelerator to ctrl+shift+q (bz #1062393)
# Patches queued for 2.1
Patch0001: 0001-Change-gtk-quit-accelerator-to-ctrl-shift-q-bz-10623.patch
# Migration CVEs: CVE-2014-0182 etc.
Patch0002: 0002-vmstate-add-VMS_MUST_EXIST.patch
Patch0003: 0003-vmstate-add-VMSTATE_VALIDATE.patch
Patch0004: 0004-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch
Patch0005: 0005-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch
Patch0006: 0006-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch
Patch0007: 0007-ahci-fix-buffer-overrun-on-invalid-state-load.patch
Patch0008: 0008-hpet-fix-buffer-overrun-on-invalid-state-load.patch
Patch0009: 0009-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch
Patch0010: 0010-pl022-fix-buffer-overun-on-invalid-state-load.patch
Patch0011: 0011-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch
Patch0012: 0012-virtio-avoid-buffer-overrun-on-incoming-migration.patch
Patch0013: 0013-virtio-validate-num_sg-when-mapping.patch
Patch0014: 0014-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch
Patch0015: 0015-ssd0323-fix-buffer-overun-on-invalid-state-load.patch
Patch0016: 0016-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch
Patch0017: 0017-zaurus-fix-buffer-overrun-on-invalid-state-load.patch
Patch0018: 0018-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch
Patch0019: 0019-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch
Patch0020: 0020-usb-sanity-check-setup_index-setup_len-in-post_load.patch
Patch0021: 0021-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch
Patch0022: 0022-openpic-avoid-buffer-overrun-on-incoming-migration.patch
Patch0023: 0023-virtio-net-out-of-bounds-buffer-write-on-load.patch
Patch0024: 0024-virtio-validate-config_len-on-load.patch
BuildRequires: SDL-devel
BuildRequires: zlib-devel
@ -726,6 +750,30 @@ CAC emulation development files.
# Change gtk quit accelerator to ctrl+shift+q (bz #1062393)
# Patches queued for 2.1
%patch0001 -p1
# Migration CVEs: CVE-2014-0182 etc.
%patch0002 -p1
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch0011 -p1
%patch0012 -p1
%patch0013 -p1
%patch0014 -p1
%patch0015 -p1
%patch0016 -p1
%patch0017 -p1
%patch0018 -p1
%patch0019 -p1
%patch0020 -p1
%patch0021 -p1
%patch0022 -p1
%patch0023 -p1
%patch0024 -p1
%build
@ -1493,6 +1541,9 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Sun May 11 2014 Cole Robinson <crobinso@redhat.com> - 2:2.0.0-4
- Migration CVEs: CVE-2014-0182 etc.
* Wed Apr 30 2014 Peter Robinson <pbrobinson@fedoraproject.org> 2:2.0.0-3
- Fix aarch64 build