aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2019-11-30 20:42:21 +0100
committerMarkus Armbruster <armbru@redhat.com>2019-12-02 16:14:38 +0100
commit5a0948d36c4cbc1c5534afac6fee99de55245d12 (patch)
tree3c7734f0f705020d9a24fc83be6ccf4d1578844b /hw
parent4dbac1aed2ca7e68e9384b0e49750d54d4cbd43d (diff)
downloadqemu-5a0948d36c4cbc1c5534afac6fee99de55245d12.zip
qemu-5a0948d36c4cbc1c5534afac6fee99de55245d12.tar.gz
qemu-5a0948d36c4cbc1c5534afac6fee99de55245d12.tar.bz2
net/virtio: Fix failover error handling crash bugs
Functions that take an Error ** parameter to pass an error to the caller expect the parameter to point to null. failover_replug_primary() violates this precondition in several places: * After qemu_opts_from_qdict() failed, *errp is no longer null. Passing it to error_setg() is wrong, and will trip the assertion in error_setv(). Messed up in commit 150ab54aa6 "net/virtio: fix re-plugging of primary device". Simply drop the error_setg(). * Passing @errp to qemu_opt_set_bool(), hotplug_handler_pre_plug(), and hotplug_handler_plug() is wrong. If one of the first two fails, *errp is no longer null. Risks tripping the same assertion. Moreover, continuing after such errors is unsafe. Messed up in commit 9711cd0dfc "net/virtio: add failover support". Fix by handling each error properly. failover_replug_primary() crashes when passed a null @errp. Also messed up in commit 9711cd0dfc. This bug can't bite as no caller actually passes null. Fix it anyway. Fixes: 9711cd0dfc3fa414f7f64935713c07134ae67971 Fixes: 150ab54aa6934583180f88a2bd540bc6fc4fbff3 Cc: Jens Freimann <jfreimann@redhat.com> Cc: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20191130194240.10517-3-armbru@redhat.com> Reviewed-by: Jens Freimann <jfreimann@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/net/virtio-net.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 87088ba..db3d7c3 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -2795,6 +2795,7 @@ static bool failover_unplug_primary(VirtIONet *n)
static bool failover_replug_primary(VirtIONet *n, Error **errp)
{
+ Error *err = NULL;
HotplugHandler *hotplug_ctrl;
PCIDevice *pdev = PCI_DEVICE(n->primary_dev);
@@ -2806,27 +2807,33 @@ static bool failover_replug_primary(VirtIONet *n, Error **errp)
qemu_find_opts("device"),
n->primary_device_dict, errp);
if (!n->primary_device_opts) {
- error_setg(errp, "virtio_net: couldn't find primary device opts");
- goto out;
+ return false;
}
}
n->primary_bus = n->primary_dev->parent_bus;
if (!n->primary_bus) {
error_setg(errp, "virtio_net: couldn't find primary bus");
- goto out;
+ return false;
}
qdev_set_parent_bus(n->primary_dev, n->primary_bus);
n->primary_should_be_hidden = false;
qemu_opt_set_bool(n->primary_device_opts,
- "partially_hotplugged", true, errp);
+ "partially_hotplugged", true, &err);
+ if (err) {
+ goto out;
+ }
hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev);
if (hotplug_ctrl) {
- hotplug_handler_pre_plug(hotplug_ctrl, n->primary_dev, errp);
+ hotplug_handler_pre_plug(hotplug_ctrl, n->primary_dev, &err);
+ if (err) {
+ goto out;
+ }
hotplug_handler_plug(hotplug_ctrl, n->primary_dev, errp);
}
out:
- return *errp == NULL;
+ error_propagate(errp, err);
+ return !err;
}
static void virtio_net_handle_migration_primary(VirtIONet *n,