aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/pxa2xx.c8
-rw-r--r--hw/audio/adlib.c6
-rw-r--r--hw/core/qdev-properties-system.c10
-rw-r--r--hw/core/qdev-properties.c11
-rw-r--r--hw/core/qdev.c20
-rw-r--r--hw/display/qxl.c7
-rw-r--r--hw/display/qxl.h1
-rw-r--r--hw/display/ssd0323.c24
-rw-r--r--hw/display/vga.c12
-rw-r--r--hw/display/vga_int.h2
-rw-r--r--hw/dma/i82374.c7
-rw-r--r--hw/dma/xilinx_axidma.c16
-rw-r--r--hw/gpio/zaurus.c10
-rw-r--r--hw/ide/ahci.c2
-rw-r--r--hw/input/tsc210x.c12
-rw-r--r--hw/intc/arm_gic.c6
-rw-r--r--hw/intc/arm_gic_kvm.c6
-rw-r--r--hw/intc/armv7m_nvic.c6
-rw-r--r--hw/intc/i8259.c4
-rw-r--r--hw/intc/openpic.c16
-rw-r--r--hw/isa/isa-bus.c11
-rw-r--r--hw/misc/tmp105.c6
-rw-r--r--hw/net/virtio-net.c20
-rw-r--r--hw/net/xilinx_axienet.c16
-rw-r--r--hw/pci/pci.c4
-rw-r--r--hw/pci/pcie_aer.c10
-rw-r--r--hw/ppc/prep.c7
-rw-r--r--hw/ppc/spapr.c26
-rw-r--r--hw/scsi/virtio-scsi.c9
-rw-r--r--hw/sd/ssi-sd.c9
-rw-r--r--hw/ssi/pl022.c14
-rw-r--r--hw/timer/hpet.c13
-rw-r--r--hw/timer/i8254.c4
-rw-r--r--hw/usb/bus.c4
-rw-r--r--hw/usb/dev-mtp.c35
-rw-r--r--hw/usb/hcd-ohci.c119
-rw-r--r--hw/virtio/virtio-balloon.c6
-rw-r--r--hw/virtio/virtio.c25
-rw-r--r--hw/watchdog/wdt_ib700.c7
39 files changed, 406 insertions, 125 deletions
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 04291488e4..e0cd847b95 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/hw/audio/adlib.c b/hw/audio/adlib.c
index 28eed81280..5dd739e541 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -86,6 +86,7 @@ typedef struct {
#ifndef HAS_YMF262
FM_OPL *opl;
#endif
+ PortioList port_list;
} AdlibState;
static AdlibState *glob_adlib;
@@ -293,7 +294,6 @@ static MemoryRegionPortio adlib_portio_list[] = {
static void adlib_realizefn (DeviceState *dev, Error **errp)
{
AdlibState *s = ADLIB(dev);
- PortioList *port_list = g_new(PortioList, 1);
struct audsettings as;
if (glob_adlib) {
@@ -349,8 +349,8 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
adlib_portio_list[0].offset = s->port;
adlib_portio_list[1].offset = s->port + 8;
- portio_list_init (port_list, OBJECT(s), adlib_portio_list, s, "adlib");
- portio_list_add (port_list, isa_address_space_io(&s->parent_obj), 0);
+ portio_list_init (&s->port_list, OBJECT(s), adlib_portio_list, s, "adlib");
+ portio_list_add (&s->port_list, isa_address_space_io(&s->parent_obj), 0);
}
static Property adlib_properties[] = {
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index de835612f0..404cf1843d 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -338,13 +338,13 @@ PropertyInfo qdev_prop_vlan = {
int qdev_prop_set_drive(DeviceState *dev, const char *name,
BlockDriverState *value)
{
- Error *errp = NULL;
+ Error *err = NULL;
const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
object_property_set_str(OBJECT(dev), bdrv_name,
- name, &errp);
- if (errp) {
- qerror_report_err(errp);
- error_free(errp);
+ name, &err);
+ if (err) {
+ qerror_report_err(err);
+ error_free(err);
return -1;
}
return 0;
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 585a8e902e..d8cb5408c3 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -751,6 +751,7 @@ static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
Property *prop = opaque;
uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
void **arrayptr = (void *)dev + prop->arrayoffset;
+ Error *local_err = NULL;
void *eltptr;
const char *arrayname;
int i;
@@ -764,8 +765,9 @@ static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
name);
return;
}
- visit_type_uint32(v, alenptr, name, errp);
- if (error_is_set(errp)) {
+ visit_type_uint32(v, alenptr, name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
if (!*alenptr) {
@@ -802,8 +804,9 @@ static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
arrayprop->prop.info->get,
arrayprop->prop.info->set,
array_element_release,
- arrayprop, errp);
- if (error_is_set(errp)) {
+ arrayprop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
}
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 60f9df1ed9..2fd5100522 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -174,14 +174,14 @@ int qdev_init(DeviceState *dev)
return 0;
}
-static void device_realize(DeviceState *dev, Error **err)
+static void device_realize(DeviceState *dev, Error **errp)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
if (dc->init) {
int rc = dc->init(dev);
if (rc < 0) {
- error_setg(err, "Device initialization failed.");
+ error_setg(errp, "Device initialization failed.");
return;
}
}
@@ -504,14 +504,14 @@ static void bus_unparent(Object *obj)
}
}
-static bool bus_get_realized(Object *obj, Error **err)
+static bool bus_get_realized(Object *obj, Error **errp)
{
BusState *bus = BUS(obj);
return bus->realized;
}
-static void bus_set_realized(Object *obj, bool value, Error **err)
+static void bus_set_realized(Object *obj, bool value, Error **errp)
{
BusState *bus = BUS(obj);
BusClass *bc = BUS_GET_CLASS(bus);
@@ -540,7 +540,7 @@ static void bus_set_realized(Object *obj, bool value, Error **err)
return;
error:
- error_propagate(err, local_err);
+ error_propagate(errp, local_err);
}
void qbus_create_inplace(void *bus, size_t size, const char *typename,
@@ -724,13 +724,13 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
}
}
-static bool device_get_realized(Object *obj, Error **err)
+static bool device_get_realized(Object *obj, Error **errp)
{
DeviceState *dev = DEVICE(obj);
return dev->realized;
}
-static void device_set_realized(Object *obj, bool value, Error **err)
+static void device_set_realized(Object *obj, bool value, Error **errp)
{
DeviceState *dev = DEVICE(obj);
DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -738,7 +738,7 @@ static void device_set_realized(Object *obj, bool value, Error **err)
Error *local_err = NULL;
if (dev->hotplugged && !dc->hotpluggable) {
- error_set(err, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
+ error_set(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
return;
}
@@ -797,14 +797,14 @@ static void device_set_realized(Object *obj, bool value, Error **err)
}
if (local_err != NULL) {
- error_propagate(err, local_err);
+ error_propagate(errp, local_err);
return;
}
dev->realized = value;
}
-static bool device_get_hotpluggable(Object *obj, Error **err)
+static bool device_get_hotpluggable(Object *obj, Error **errp)
{
DeviceClass *dc = DEVICE_GET_CLASS(obj);
DeviceState *dev = DEVICE(obj);
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index e9c54d7399..7fb83e4eaf 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2055,7 +2055,6 @@ static int qxl_init_primary(PCIDevice *dev)
{
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
VGACommonState *vga = &qxl->vga;
- PortioList *qxl_vga_port_list = g_new(PortioList, 1);
int rc;
qxl->id = 0;
@@ -2064,10 +2063,10 @@ static int qxl_init_primary(PCIDevice *dev)
vga_common_init(vga, OBJECT(dev), true);
vga_init(vga, OBJECT(dev),
pci_address_space(dev), pci_address_space_io(dev), false);
- portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,
+ portio_list_init(&qxl->vga_port_list, OBJECT(dev), qxl_vga_portio_list,
vga, "vga");
- portio_list_set_flush_coalesced(qxl_vga_port_list);
- portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
+ portio_list_set_flush_coalesced(&qxl->vga_port_list);
+ portio_list_add(&qxl->vga_port_list, pci_address_space_io(dev), 0x3b0);
vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
qemu_spice_display_init_common(&qxl->ssd);
diff --git a/hw/display/qxl.h b/hw/display/qxl.h
index c5de3d7075..412e346b68 100644
--- a/hw/display/qxl.h
+++ b/hw/display/qxl.h
@@ -32,6 +32,7 @@ enum qxl_mode {
typedef struct PCIQXLDevice {
PCIDevice pci;
+ PortioList vga_port_list;
SimpleSpiceDisplay ssd;
int id;
uint32_t debug;
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 971152edbd..97270077e2 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/hw/display/vga.c b/hw/display/vga.c
index c4c3238d5f..8cd6afe83a 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -2355,8 +2355,6 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
{
MemoryRegion *vga_io_memory;
const MemoryRegionPortio *vga_ports, *vbe_ports;
- PortioList *vga_port_list = g_new(PortioList, 1);
- PortioList *vbe_port_list = g_new(PortioList, 1);
qemu_register_reset(vga_reset, s);
@@ -2371,13 +2369,13 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
1);
memory_region_set_coalescing(vga_io_memory);
if (init_vga_ports) {
- portio_list_init(vga_port_list, obj, vga_ports, s, "vga");
- portio_list_set_flush_coalesced(vga_port_list);
- portio_list_add(vga_port_list, address_space_io, 0x3b0);
+ portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
+ portio_list_set_flush_coalesced(&s->vga_port_list);
+ portio_list_add(&s->vga_port_list, address_space_io, 0x3b0);
}
if (vbe_ports) {
- portio_list_init(vbe_port_list, obj, vbe_ports, s, "vbe");
- portio_list_add(vbe_port_list, address_space_io, 0x1ce);
+ portio_list_init(&s->vbe_port_list, obj, vbe_ports, s, "vbe");
+ portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce);
}
}
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index d42ac926e3..5320abdc07 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -124,6 +124,8 @@ typedef struct VGACommonState {
void (*get_resolution)(struct VGACommonState *s,
int *pwidth,
int *pheight);
+ PortioList vga_port_list;
+ PortioList vbe_port_list;
/* bochs vbe state */
uint16_t vbe_index;
uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c
index dc7a767ee2..b8ad2e64ec 100644
--- a/hw/dma/i82374.c
+++ b/hw/dma/i82374.c
@@ -39,6 +39,7 @@ do { fprintf(stderr, "i82374 ERROR: " fmt , ## __VA_ARGS__); } while (0)
typedef struct I82374State {
uint8_t commands[8];
qemu_irq out;
+ PortioList port_list;
} I82374State;
static const VMStateDescription vmstate_i82374 = {
@@ -137,10 +138,10 @@ static void i82374_isa_realize(DeviceState *dev, Error **errp)
{
ISAi82374State *isa = I82374(dev);
I82374State *s = &isa->state;
- PortioList *port_list = g_new(PortioList, 1);
- portio_list_init(port_list, OBJECT(isa), i82374_portio_list, s, "i82374");
- portio_list_add(port_list, isa_address_space_io(&isa->parent_obj),
+ portio_list_init(&s->port_list, OBJECT(isa), i82374_portio_list, s,
+ "i82374");
+ portio_list_add(&s->port_list, isa_address_space_io(&isa->parent_obj),
isa->iobase);
i82374_realize(s, errp);
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index 14b887bfa8..cc90eb5110 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -534,24 +534,24 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev);
XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
&s->rx_control_dev);
- Error *local_errp = NULL;
+ Error *local_err = NULL;
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&ds->dma,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
- &local_errp);
+ &local_err);
object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&cs->dma,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
- &local_errp);
- if (local_errp) {
+ &local_err);
+ if (local_err) {
goto xilinx_axidma_realize_fail;
}
- object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_errp);
- object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_errp);
- if (local_errp) {
+ object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_err);
+ object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_err);
+ if (local_err) {
goto xilinx_axidma_realize_fail;
}
@@ -567,7 +567,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
xilinx_axidma_realize_fail:
if (!*errp) {
- *errp = local_errp;
+ *errp = local_err;
}
}
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index dc79a8baa6..8e2ce049de 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/hw/ide/ahci.c b/hw/ide/ahci.c
index 50327ffdf1..e57c5837d2 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/hw/input/tsc210x.c b/hw/input/tsc210x.c
index 485c9e5753..aa5b6886ea 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/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 955b8d4945..1532ef9482 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -797,9 +797,11 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
GICState *s = ARM_GIC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
ARMGICClass *agc = ARM_GIC_GET_CLASS(s);
+ Error *local_err = NULL;
- agc->parent_realize(dev, errp);
- if (error_is_set(errp)) {
+ agc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 719d2277ec..5038885afd 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -517,10 +517,12 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
GICState *s = KVM_ARM_GIC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
+ Error *local_err = NULL;
int ret;
- kgc->parent_realize(dev, errp);
- if (error_is_set(errp)) {
+ kgc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index f5b0c3be6f..9aa8ab208f 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -474,14 +474,16 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
{
nvic_state *s = NVIC(dev);
NVICClass *nc = NVIC_GET_CLASS(s);
+ Error *local_err = NULL;
/* The NVIC always has only one CPU */
s->gic.num_cpu = 1;
/* Tell the common code we're an NVIC */
s->gic.revision = 0xffffffff;
s->num_irq = s->gic.num_irq;
- nc->parent_realize(dev, errp);
- if (error_is_set(errp)) {
+ nc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
gic_init_irqs_and_distributor(&s->gic, s->num_irq);
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index c6f248b145..ec01393e4f 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -412,7 +412,7 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
},
};
-static void pic_realize(DeviceState *dev, Error **err)
+static void pic_realize(DeviceState *dev, Error **errp)
{
PICCommonState *s = PIC_COMMON(dev);
PICClass *pc = PIC_GET_CLASS(dev);
@@ -425,7 +425,7 @@ static void pic_realize(DeviceState *dev, Error **err)
qdev_init_gpio_out(dev, s->int_out, ARRAY_SIZE(s->int_out));
qdev_init_gpio_in(dev, pic_set_irq, 8);
- pc->parent_realize(dev, err);
+ pc->parent_realize(dev, errp);
}
void pic_info(Monitor *mon, const QDict *qdict)
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
index be76fbd78f..17136c9333 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/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 55d01008d3..b28981bfde 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -108,15 +108,20 @@ void isa_register_portio_list(ISADevice *dev, uint16_t start,
const MemoryRegionPortio *pio_start,
void *opaque, const char *name)
{
- PortioList *piolist = g_new(PortioList, 1);
+ PortioList piolist;
/* START is how we should treat DEV, regardless of the actual
contents of the portio array. This is how the old code
actually handled e.g. the FDC device. */
isa_init_ioport(dev, start);
- portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
- portio_list_add(piolist, isabus->address_space_io, start);
+ /* FIXME: the device should store created PortioList in its state. Note
+ that DEV can be NULL here and that single device can register several
+ portio lists. Current implementation is leaking memory allocated
+ in portio_list_init. The leak is not critical because it happens only
+ at initialization time. */
+ portio_list_init(&piolist, OBJECT(dev), pio_start, opaque, name);
+ portio_list_add(&piolist, isabus->address_space_io, start);
}
static void isa_device_init(Object *obj)
diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c
index 63aa3d6277..636ee97b16 100644
--- a/hw/misc/tmp105.c
+++ b/hw/misc/tmp105.c
@@ -68,10 +68,12 @@ static void tmp105_set_temperature(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
TMP105State *s = TMP105(obj);
+ Error *local_err = NULL;
int64_t temp;
- visit_type_int(v, &temp, name, errp);
- if (error_is_set(errp)) {
+ visit_type_int(v, &temp, name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
if (temp >= 128000 || temp < -128000) {
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 33bd233a2d..940a7cfe54 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;
}
@@ -1407,6 +1414,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/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index dbeb3c9a25..cd952d2514 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -945,24 +945,24 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev);
XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(
&s->rx_control_dev);
- Error *local_errp = NULL;
+ Error *local_err = NULL;
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
(Object **) &ds->enet,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
- &local_errp);
+ &local_err);
object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
(Object **) &cs->enet,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
- &local_errp);
- if (local_errp) {
+ &local_err);
+ if (local_err) {
goto xilinx_enet_realize_fail;
}
- object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_errp);
- object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_errp);
- if (local_errp) {
+ object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_err);
+ object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_err);
+ if (local_err) {
goto xilinx_enet_realize_fail;
}
@@ -981,7 +981,7 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
xilinx_enet_realize_fail:
if (!*errp) {
- *errp = local_errp;
+ *errp = local_err;
}
}
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/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()
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index e2436512f7..585937321f 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -361,6 +361,8 @@ static const MemoryRegionPortio prep_portio_list[] = {
PORTIO_END_OF_LIST(),
};
+static PortioList prep_port_list;
+
/* PowerPC PREP hardware initialisation */
static void ppc_prep_init(QEMUMachineInitArgs *args)
{
@@ -375,7 +377,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
CPUPPCState *env = NULL;
nvram_t nvram;
M48t59State *m48t59;
- PortioList *port_list = g_new(PortioList, 1);
#if 0
MemoryRegion *xcsr = g_new(MemoryRegion, 1);
#endif
@@ -542,8 +543,8 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
cpu = POWERPC_CPU(first_cpu);
sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET];
- portio_list_init(port_list, NULL, prep_portio_list, sysctrl, "prep");
- portio_list_add(port_list, isa_address_space_io(isa), 0x0);
+ portio_list_init(&prep_port_list, NULL, prep_portio_list, sysctrl, "prep");
+ portio_list_add(&prep_port_list, isa_address_space_io(isa), 0x0);
/* PowerPC control and status register group */
#if 0
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a11e1217b9..b4ce950bbd 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1419,19 +1419,6 @@ static int spapr_kvm_type(const char *vm_type)
exit(1);
}
-static QEMUMachine spapr_machine = {
- .name = "pseries",
- .desc = "pSeries Logical Partition (PAPR compliant)",
- .is_default = 1,
- .init = ppc_spapr_init,
- .reset = ppc_spapr_reset,
- .block_default_type = IF_SCSI,
- .max_cpus = MAX_CPUS,
- .no_parallel = 1,
- .default_boot_order = NULL,
- .kvm_type = spapr_kvm_type,
-};
-
/*
* Implementation of an interface to adjust firmware patch
* for the bootindex property handling.
@@ -1494,7 +1481,17 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc);
FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
- mc->qemu_machine = data;
+ mc->name = "pseries";
+ mc->desc = "pSeries Logical Partition (PAPR compliant)";
+ mc->is_default = 1;
+ mc->init = ppc_spapr_init;
+ mc->reset = ppc_spapr_reset;
+ mc->block_default_type = IF_SCSI;
+ mc->max_cpus = MAX_CPUS;
+ mc->no_parallel = 1;
+ mc->default_boot_order = NULL;
+ mc->kvm_type = spapr_kvm_type;
+
fwc->get_dev_path = spapr_get_fw_dev_path;
}
@@ -1502,7 +1499,6 @@ static const TypeInfo spapr_machine_info = {
.name = TYPE_SPAPR_MACHINE,
.parent = TYPE_MACHINE,
.class_init = spapr_machine_class_init,
- .class_data = &spapr_machine,
.interfaces = (InterfaceInfo[]) {
{ TYPE_FW_PATH_PROVIDER },
{ }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index b0d7517cb1..175219376c 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/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 3273c8a31f..b012e57f64 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/hw/ssi/pl022.c b/hw/ssi/pl022.c
index fd479effb9..b19bc7174a 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/hw/timer/hpet.c b/hw/timer/hpet.c
index e15d6bcac7..2792f89c66 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/hw/timer/i8254.c b/hw/timer/i8254.c
index 28152d88ea..3450c98637 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -322,7 +322,7 @@ static void pit_post_load(PITCommonState *s)
}
}
-static void pit_realizefn(DeviceState *dev, Error **err)
+static void pit_realizefn(DeviceState *dev, Error **errp)
{
PITCommonState *pit = PIT_COMMON(dev);
PITClass *pc = PIT_GET_CLASS(dev);
@@ -338,7 +338,7 @@ static void pit_realizefn(DeviceState *dev, Error **err)
qdev_init_gpio_in(dev, pit_irq_control, 1);
- pc->parent_realize(dev, err);
+ pc->parent_realize(dev, errp);
}
static Property pit_properties[] = {
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index fe70429304..e48b19fc29 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/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 8b44032900..943f930404 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -50,6 +50,7 @@ enum mtp_code {
RES_INVALID_TRANSACTION_ID = 0x2004,
RES_OPERATION_NOT_SUPPORTED = 0x2005,
RES_PARAMETER_NOT_SUPPORTED = 0x2006,
+ RES_INCOMPLETE_TRANSFER = 0x2007,
RES_INVALID_STORAGE_ID = 0x2008,
RES_INVALID_OBJECT_HANDLE = 0x2009,
RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014,
@@ -294,7 +295,7 @@ static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle,
goto ignore;
}
- fprintf(stderr, "%s: 0x%x %s\n", __func__, o->handle, o->path);
+ trace_usb_mtp_object_alloc(s->dev.addr, o->handle, o->path);
QTAILQ_INSERT_TAIL(&s->objects, o, next);
return o;
@@ -310,7 +311,7 @@ static void usb_mtp_object_free(MTPState *s, MTPObject *o)
{
int i;
- fprintf(stderr, "%s: 0x%x %s\n", __func__, o->handle, o->path);
+ trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path);
QTAILQ_REMOVE(&s->objects, o, next);
for (i = 0; i < o->nchildren; i++) {
@@ -416,7 +417,7 @@ static void usb_mtp_add_u32(MTPData *data, uint32_t val)
static void usb_mtp_add_u64(MTPData *data, uint64_t val)
{
- usb_mtp_realloc(data, 4);
+ usb_mtp_realloc(data, 8);
data->data[data->length++] = (val >> 0) & 0xff;
data->data[data->length++] = (val >> 8) & 0xff;
data->data[data->length++] = (val >> 16) & 0xff;
@@ -424,7 +425,7 @@ static void usb_mtp_add_u64(MTPData *data, uint64_t val)
data->data[data->length++] = (val >> 32) & 0xff;
data->data[data->length++] = (val >> 40) & 0xff;
data->data[data->length++] = (val >> 48) & 0xff;
- data->data[data->length++] = (val >> 54) & 0xff;
+ data->data[data->length++] = (val >> 56) & 0xff;
}
static void usb_mtp_add_u16_array(MTPData *data, uint32_t len,
@@ -533,7 +534,7 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c)
trace_usb_mtp_op_get_device_info(s->dev.addr);
- usb_mtp_add_u16(d, 0x0100);
+ usb_mtp_add_u16(d, 100);
usb_mtp_add_u32(d, 0xffffffff);
usb_mtp_add_u16(d, 0x0101);
usb_mtp_add_wstr(d, L"");
@@ -548,7 +549,7 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c)
usb_mtp_add_wstr(d, L"" MTP_MANUFACTURER);
usb_mtp_add_wstr(d, L"" MTP_PRODUCT);
usb_mtp_add_wstr(d, L"0.1");
- usb_mtp_add_wstr(d, L"123456789abcdef123456789abcdef");
+ usb_mtp_add_wstr(d, L"0123456789abcdef0123456789abcdef");
return d;
}
@@ -669,6 +670,7 @@ static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c,
d->fd = open(o->path, O_RDONLY);
if (d->fd == -1) {
+ usb_mtp_data_free(d);
return NULL;
}
d->length = o->stat.st_size;
@@ -688,6 +690,7 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c,
d->fd = open(o->path, O_RDONLY);
if (d->fd == -1) {
+ usb_mtp_data_free(d);
return NULL;
}
@@ -843,8 +846,7 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
res0 = data_in->length;
break;
default:
- fprintf(stderr, "%s: unknown command code 0x%04x\n",
- __func__, c->code);
+ trace_usb_mtp_op_unknown(s->dev.addr, c->code);
usb_mtp_queue_result(s, RES_OPERATION_NOT_SUPPORTED,
c->trans, 0, 0, 0);
return;
@@ -892,6 +894,7 @@ static void usb_mtp_handle_control(USBDevice *dev, USBPacket *p,
static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)
{
+ /* we don't use async packets, so this should never be called */
fprintf(stderr, "%s\n", __func__);
}
@@ -944,7 +947,8 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
}
rc = read(d->fd, d->data, dlen);
if (rc != dlen) {
- fprintf(stderr, "%s: TODO: handle read error\n", __func__);
+ memset(d->data, 0, dlen);
+ s->result->code = RES_INCOMPLETE_TRANSFER;
}
usb_packet_copy(p, d->data, dlen);
}
@@ -996,6 +1000,14 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
cmd.argc = (le32_to_cpu(container.length) - sizeof(container))
/ sizeof(uint32_t);
cmd.trans = le32_to_cpu(container.trans);
+ if (cmd.argc > ARRAY_SIZE(cmd.argv)) {
+ cmd.argc = ARRAY_SIZE(cmd.argv);
+ }
+ if (p->iov.size < sizeof(container) + cmd.argc * sizeof(uint32_t)) {
+ trace_usb_mtp_stall(s->dev.addr, "packet too small");
+ p->status = USB_RET_STALL;
+ return;
+ }
usb_packet_copy(p, &params, cmd.argc * sizeof(uint32_t));
for (i = 0; i < cmd.argc; i++) {
cmd.argv[i] = le32_to_cpu(params[i]);
@@ -1009,8 +1021,7 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
usb_mtp_command(s, &cmd);
break;
default:
- iov_hexdump(p->iov.iov, p->iov.niov, stderr, "mtp-out", 32);
- trace_usb_mtp_stall(s->dev.addr, "TODO: implement data-out");
+ /* not needed as long as the mtp device is read-only */
p->status = USB_RET_STALL;
return;
}
@@ -1044,7 +1055,7 @@ static int usb_mtp_initfn(USBDevice *dev)
QTAILQ_INIT(&s->objects);
if (s->desc == NULL) {
s->desc = strrchr(s->root, '/');
- if (s->desc) {
+ if (s->desc && s->desc[0]) {
s->desc = g_strdup(s->desc + 1);
} else {
s->desc = g_strdup("none");
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 93f186f5e7..cd87074862 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -80,13 +80,13 @@ typedef struct {
uint32_t bulk_head, bulk_cur;
uint32_t per_cur;
uint32_t done;
- int done_count;
+ int32_t done_count;
/* Frame counter partition */
- uint32_t fsmps:15;
- uint32_t fit:1;
- uint32_t fi:14;
- uint32_t frt:1;
+ uint16_t fsmps;
+ uint8_t fit;
+ uint16_t fi;
+ uint8_t frt;
uint16_t frame_number;
uint16_t padding;
uint32_t pstart;
@@ -111,7 +111,7 @@ typedef struct {
USBPacket usb_packet;
uint8_t usb_buf[8192];
uint32_t async_td;
- int async_complete;
+ bool async_complete;
} OHCIState;
@@ -693,7 +693,7 @@ static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
#ifdef DEBUG_PACKET
DPRINTF("Async packet complete\n");
#endif
- ohci->async_complete = 1;
+ ohci->async_complete = true;
ohci_process_lists(ohci, 1);
}
@@ -1058,7 +1058,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
#endif
if (completion) {
ohci->async_td = 0;
- ohci->async_complete = 0;
+ ohci->async_complete = false;
} else {
if (ohci->async_td) {
/* ??? The hardware should allow one active packet per
@@ -1984,6 +1984,108 @@ static Property ohci_pci_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static const VMStateDescription vmstate_ohci_state_port = {
+ .name = "ohci-core/port",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(ctrl, OHCIPort),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static bool ohci_eof_timer_needed(void *opaque)
+{
+ OHCIState *ohci = opaque;
+
+ return ohci->eof_timer != NULL;
+}
+
+static int ohci_eof_timer_pre_load(void *opaque)
+{
+ OHCIState *ohci = opaque;
+
+ ohci_bus_start(ohci);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_ohci_eof_timer = {
+ .name = "ohci-core/eof-timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .pre_load = ohci_eof_timer_pre_load,
+ .fields = (VMStateField []) {
+ VMSTATE_TIMER(eof_timer, OHCIState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+const VMStateDescription vmstate_ohci_state = {
+ .name = "ohci-core",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT64(sof_time, OHCIState),
+ VMSTATE_UINT32(ctl, OHCIState),
+ VMSTATE_UINT32(status, OHCIState),
+ VMSTATE_UINT32(intr_status, OHCIState),
+ VMSTATE_UINT32(intr, OHCIState),
+ VMSTATE_UINT32(hcca, OHCIState),
+ VMSTATE_UINT32(ctrl_head, OHCIState),
+ VMSTATE_UINT32(ctrl_cur, OHCIState),
+ VMSTATE_UINT32(bulk_head, OHCIState),
+ VMSTATE_UINT32(bulk_cur, OHCIState),
+ VMSTATE_UINT32(per_cur, OHCIState),
+ VMSTATE_UINT32(done, OHCIState),
+ VMSTATE_INT32(done_count, OHCIState),
+ VMSTATE_UINT16(fsmps, OHCIState),
+ VMSTATE_UINT8(fit, OHCIState),
+ VMSTATE_UINT16(fi, OHCIState),
+ VMSTATE_UINT8(frt, OHCIState),
+ VMSTATE_UINT16(frame_number, OHCIState),
+ VMSTATE_UINT16(padding, OHCIState),
+ VMSTATE_UINT32(pstart, OHCIState),
+ VMSTATE_UINT32(lst, OHCIState),
+ VMSTATE_UINT32(rhdesc_a, OHCIState),
+ VMSTATE_UINT32(rhdesc_b, OHCIState),
+ VMSTATE_UINT32(rhstatus, OHCIState),
+ VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0,
+ vmstate_ohci_state_port, OHCIPort),
+ VMSTATE_UINT32(hstatus, OHCIState),
+ VMSTATE_UINT32(hmask, OHCIState),
+ VMSTATE_UINT32(hreset, OHCIState),
+ VMSTATE_UINT32(htest, OHCIState),
+ VMSTATE_UINT32(old_ctl, OHCIState),
+ VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192),
+ VMSTATE_UINT32(async_td, OHCIState),
+ VMSTATE_BOOL(async_complete, OHCIState),
+ VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection []) {
+ {
+ .vmsd = &vmstate_ohci_eof_timer,
+ .needed = ohci_eof_timer_needed,
+ } , {
+ /* empty */
+ }
+ }
+};
+
+static const VMStateDescription vmstate_ohci = {
+ .name = "ohci",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(parent_obj, OHCIPCIState),
+ VMSTATE_STRUCT(state, OHCIPCIState, 1, vmstate_ohci_state, OHCIState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void ohci_pci_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1997,6 +2099,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data)
dc->desc = "Apple USB Controller";
dc->props = ohci_pci_properties;
dc->hotpluggable = false;
+ dc->vmsd = &vmstate_ohci;
}
static const TypeInfo ohci_pci_info = {
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a470a0b3a6..971a921777 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -142,10 +142,12 @@ static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v,
Error **errp)
{
VirtIOBalloon *s = opaque;
+ Error *local_err = NULL;
int64_t value;
- visit_type_int(v, &value, name, errp);
- if (error_is_set(errp)) {
+ visit_type_int(v, &value, name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index aeabf3a459..7f4e7eca0e 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);
@@ -891,7 +897,9 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val)
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
- int num, i, ret;
+ int i, ret;
+ int32_t config_len;
+ uint32_t num;
uint32_t features;
uint32_t supported_features;
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@@ -906,6 +914,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) {
@@ -914,11 +925,21 @@ 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);
+ 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/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c
index bc994a4c32..68b33e12be 100644
--- a/hw/watchdog/wdt_ib700.c
+++ b/hw/watchdog/wdt_ib700.c
@@ -42,6 +42,8 @@ typedef struct IB700state {
ISADevice parent_obj;
QEMUTimer *timer;
+
+ PortioList port_list;
} IB700State;
/* This is the timer. We use a global here because the watchdog
@@ -106,14 +108,13 @@ static const MemoryRegionPortio wdt_portio_list[] = {
static void wdt_ib700_realize(DeviceState *dev, Error **errp)
{
IB700State *s = IB700(dev);
- PortioList *port_list = g_new(PortioList, 1);
ib700_debug("watchdog init\n");
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ib700_timer_expired, s);
- portio_list_init(port_list, OBJECT(s), wdt_portio_list, s, "ib700");
- portio_list_add(port_list, isa_address_space_io(&s->parent_obj), 0);
+ portio_list_init(&s->port_list, OBJECT(s), wdt_portio_list, s, "ib700");
+ portio_list_add(&s->port_list, isa_address_space_io(&s->parent_obj), 0);
}
static void wdt_ib700_reset(DeviceState *dev)