From 5f691ff91d323b6f97c6600405a7f9dc115a0ad1 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 3 Apr 2014 19:51:31 +0300 Subject: 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 --- hw/pci/pcie_aer.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'hw/pci') diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 991502e517..535be2c08a 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() -- cgit 1.4.1 From 3476436a44c29725efef0cabf5b3ea4e70054d57 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 3 Apr 2014 19:52:21 +0300 Subject: 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 --- hw/pci/pci.c | 4 ++-- include/migration/vmstate.h | 2 +- target-arm/machine.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'hw/pci') diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 2a9f08eb0a..517ff2a21b 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 5b7137058d..7e45048355 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 b967223fc0..810ba27f40 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -248,7 +248,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), -- cgit 1.4.1