From 70114f9e561060efff73e19762d43ed170eb80da Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: May 11 2014 23:07:44 +0000 Subject: Migration CVEs: CVE-2014-0182 etc. --- diff --git a/0001-Change-gtk-quit-accelerator-to-ctrl-shift-q-bz-10623.patch b/0001-Change-gtk-quit-accelerator-to-ctrl-shift-q-bz-10623.patch index 9c0524d..3fc7beb 100644 --- a/0001-Change-gtk-quit-accelerator-to-ctrl-shift-q-bz-10623.patch +++ b/0001-Change-gtk-quit-accelerator-to-ctrl-shift-q-bz-10623.patch @@ -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 Date: Wed, 19 Mar 2014 14:57:27 -0400 Subject: [PATCH] Change gtk quit accelerator to ctrl+shift+q (bz 1062393) diff --git a/0002-vmstate-add-VMS_MUST_EXIST.patch b/0002-vmstate-add-VMS_MUST_EXIST.patch new file mode 100644 index 0000000..073abd8 --- /dev/null +++ b/0002-vmstate-add-VMS_MUST_EXIST.patch @@ -0,0 +1,57 @@ +From 105071cc70a454680e6bf11e2d9d7b73c7ce7491 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Juan Quintela +(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++; + } diff --git a/0003-vmstate-add-VMSTATE_VALIDATE.patch b/0003-vmstate-add-VMSTATE_VALIDATE.patch new file mode 100644 index 0000000..775a9ab --- /dev/null +++ b/0003-vmstate-add-VMSTATE_VALIDATE.patch @@ -0,0 +1,33 @@ +From d9e0cb134eefe5104b404b91eaf969a2cd74bd9f Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Juan Quintela +(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), \ diff --git a/0004-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch b/0004-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch new file mode 100644 index 0000000..1b315c5 --- /dev/null +++ b/0004-virtio-net-fix-buffer-overflow-on-invalid-state-load.patch @@ -0,0 +1,59 @@ +From ea96c6a9c91da1923aa922a781fd7abbf9f51b6c Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Laszlo Ersek +Signed-off-by: Juan Quintela +(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/0005-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch b/0005-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch new file mode 100644 index 0000000..3648d73 --- /dev/null +++ b/0005-virtio-net-out-of-bounds-buffer-write-on-invalid-sta.patch @@ -0,0 +1,55 @@ +From 9229c44bfa3549085ac68265d9be95a8552c4fa4 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Acked-by: Jason Wang +Reviewed-by: Michael Roth +Signed-off-by: Juan Quintela +(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); + } diff --git a/0006-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch b/0006-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch new file mode 100644 index 0000000..c47af93 --- /dev/null +++ b/0006-virtio-out-of-bounds-buffer-write-on-invalid-state-l.patch @@ -0,0 +1,52 @@ +From 23f0db5c309893195025bc75402f3f9e1b4de743 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Reviewed-by: Michael Roth +Signed-off-by: Juan Quintela +(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) { diff --git a/0007-ahci-fix-buffer-overrun-on-invalid-state-load.patch b/0007-ahci-fix-buffer-overrun-on-invalid-state-load.patch new file mode 100644 index 0000000..07a379c --- /dev/null +++ b/0007-ahci-fix-buffer-overrun-on-invalid-state-load.patch @@ -0,0 +1,36 @@ +From 95fa012ed61e1e8b88d701b8f75b38dc5edb16e2 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Peter Maydell +Signed-off-by: Juan Quintela +(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() + }, + }; diff --git a/0008-hpet-fix-buffer-overrun-on-invalid-state-load.patch b/0008-hpet-fix-buffer-overrun-on-invalid-state-load.patch new file mode 100644 index 0000000..fa1c624 --- /dev/null +++ b/0008-hpet-fix-buffer-overrun-on-invalid-state-load.patch @@ -0,0 +1,51 @@ +From 5e0e0a12887c9e70356c23d20b08b08eabd4a6df Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Juan Quintela +(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() diff --git a/0009-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch b/0009-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch new file mode 100644 index 0000000..5b22295 --- /dev/null +++ b/0009-hw-pci-pcie_aer.c-fix-buffer-overruns-on-invalid-sta.patch @@ -0,0 +1,55 @@ +From b6f53085cc618bc7e58be702afacad1b5dcae5ba Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Reported-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Juan Quintela +(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() diff --git a/0010-pl022-fix-buffer-overun-on-invalid-state-load.patch b/0010-pl022-fix-buffer-overun-on-invalid-state-load.patch new file mode 100644 index 0000000..f48fa74 --- /dev/null +++ b/0010-pl022-fix-buffer-overun-on-invalid-state-load.patch @@ -0,0 +1,50 @@ +From 872fc04ecd90e0ca4d8ac4565b3a9f246c070873 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Juan Quintela +(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/0011-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch b/0011-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch new file mode 100644 index 0000000..46a77b0 --- /dev/null +++ b/0011-vmstate-fix-buffer-overflow-in-target-arm-machine.c.patch @@ -0,0 +1,52 @@ +From acf45756e165664f6d70025c02ddca563adee496 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Juan Quintela +(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; + } diff --git a/0012-virtio-avoid-buffer-overrun-on-incoming-migration.patch b/0012-virtio-avoid-buffer-overrun-on-incoming-migration.patch new file mode 100644 index 0000000..69bdf95 --- /dev/null +++ b/0012-virtio-avoid-buffer-overrun-on-incoming-migration.patch @@ -0,0 +1,40 @@ +From 9b5cc034e1ed5b2ebc133029d4f865f186c6b895 Mon Sep 17 00:00:00 2001 +From: Michael Roth +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 +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Peter Maydell +Signed-off-by: Juan Quintela +(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) { diff --git a/0013-virtio-validate-num_sg-when-mapping.patch b/0013-virtio-validate-num_sg-when-mapping.patch new file mode 100644 index 0000000..91de06c --- /dev/null +++ b/0013-virtio-validate-num_sg-when-mapping.patch @@ -0,0 +1,41 @@ +From f1344659fd93ea0dfb9d8d1af25993e57584c773 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Cc: Amit Shah +Signed-off-by: Juan Quintela +(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); diff --git a/0014-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch b/0014-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch new file mode 100644 index 0000000..94d2d4d --- /dev/null +++ b/0014-pxa2xx-avoid-buffer-overrun-on-incoming-migration.patch @@ -0,0 +1,51 @@ +From 43b30dec4d07aa81ff5f2dc3b0a064fa589fd3af Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Reported-by: Michael Roth +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Peter Maydell +Reviewed-by: Don Koch +Signed-off-by: Juan Quintela +(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); diff --git a/0015-ssd0323-fix-buffer-overun-on-invalid-state-load.patch b/0015-ssd0323-fix-buffer-overun-on-invalid-state-load.patch new file mode 100644 index 0000000..c0bc8e9 --- /dev/null +++ b/0015-ssd0323-fix-buffer-overun-on-invalid-state-load.patch @@ -0,0 +1,77 @@ +From 0cbd8c5754d6f56b53717e92353772777a799b87 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Reviewed-by: Peter Maydell +Signed-off-by: Juan Quintela +(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); diff --git a/0016-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch b/0016-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch new file mode 100644 index 0000000..33fc0c7 --- /dev/null +++ b/0016-tsc210x-fix-buffer-overrun-on-invalid-state-load.patch @@ -0,0 +1,50 @@ +From 984fcc9ad2abc4429422c045d68e17f1eb1fa4b2 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Juan Quintela +(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); diff --git a/0017-zaurus-fix-buffer-overrun-on-invalid-state-load.patch b/0017-zaurus-fix-buffer-overrun-on-invalid-state-load.patch new file mode 100644 index 0000000..9b442d4 --- /dev/null +++ b/0017-zaurus-fix-buffer-overrun-on-invalid-state-load.patch @@ -0,0 +1,54 @@ +From 985b046012f258fd5a2164fb85e9d792f574697c Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Juan Quintela +(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/0018-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch b/0018-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch new file mode 100644 index 0000000..6c8218d --- /dev/null +++ b/0018-virtio-scsi-fix-buffer-overrun-on-invalid-state-load.patch @@ -0,0 +1,67 @@ +From 579bb2000dbcd8a415660e76d31f521d87ac1302 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Juan Quintela +(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); diff --git a/0019-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch b/0019-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch new file mode 100644 index 0000000..8b93785 --- /dev/null +++ b/0019-vmstate-s-VMSTATE_INT32_LE-VMSTATE_INT32_POSITIVE_LE.patch @@ -0,0 +1,65 @@ +From 83bb87c00e9970a1771ddcad3fd99091f5b2719c Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Juan Quintela +(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), diff --git a/0020-usb-sanity-check-setup_index-setup_len-in-post_load.patch b/0020-usb-sanity-check-setup_index-setup_len-in-post_load.patch new file mode 100644 index 0000000..824140c --- /dev/null +++ b/0020-usb-sanity-check-setup_index-setup_len-in-post_load.patch @@ -0,0 +1,38 @@ +From a608c9c4150820ec64f5f25f6ebe244906c015da Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Gerd Hoffmann +Signed-off-by: Juan Quintela +(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; + } diff --git a/0021-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch b/0021-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch new file mode 100644 index 0000000..ac1e790 --- /dev/null +++ b/0021-ssi-sd-fix-buffer-overrun-on-invalid-state-load.patch @@ -0,0 +1,41 @@ +From d2c50b94a808f06d778746aec63ce2cb4eb1222f Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Juan Quintela +(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); + diff --git a/0022-openpic-avoid-buffer-overrun-on-incoming-migration.patch b/0022-openpic-avoid-buffer-overrun-on-incoming-migration.patch new file mode 100644 index 0000000..b9404dc --- /dev/null +++ b/0022-openpic-avoid-buffer-overrun-on-incoming-migration.patch @@ -0,0 +1,72 @@ +From 70488d5f1746b720bc141ea6b9850585e9c42121 Mon Sep 17 00:00:00 2001 +From: Michael Roth +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 +Reviewed-by: Alexander Graf +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Juan Quintela +(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: diff --git a/0023-virtio-net-out-of-bounds-buffer-write-on-load.patch b/0023-virtio-net-out-of-bounds-buffer-write-on-load.patch new file mode 100644 index 0000000..cf100f3 --- /dev/null +++ b/0023-virtio-net-out-of-bounds-buffer-write-on-load.patch @@ -0,0 +1,55 @@ +From 1a29e58f9f23846d0e105a3157629786fc624f65 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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 +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Juan Quintela +(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; + } diff --git a/0024-virtio-validate-config_len-on-load.patch b/0024-virtio-validate-config_len-on-load.patch new file mode 100644 index 0000000..9e6dde4 --- /dev/null +++ b/0024-virtio-validate-config_len-on-load.patch @@ -0,0 +1,52 @@ +From 94998eaa5ef06ba17ad12976ac84801033a28582 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +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" +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Juan Quintela + +-- + +v2: use %ix and %zx to print config_len values +Signed-off-by: Juan Quintela +(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); diff --git a/qemu.spec b/qemu.spec index 7d335d8..17ede15 100644 --- a/qemu.spec +++ b/qemu.spec @@ -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 - 2:2.0.0-4 +- Migration CVEs: CVE-2014-0182 etc. + * Wed Apr 30 2014 Peter Robinson 2:2.0.0-3 - Fix aarch64 build