On Tue, 29 Oct 2019 at 23:01, Michael S. Tsirkin <m...@redhat.com> wrote:
>
> From: Jens Freimann <jfreim...@redhat.com>
>
> This patch adds support to handle failover device pairs of a virtio-net
> device and a (vfio-)pci device, where the virtio-net acts as the standby
> device and the (vfio-)pci device as the primary.

Hi; Coverity reports some dereference-before-NULL-check errors
in this commit:




> +static bool failover_replug_primary(VirtIONet *n, Error **errp)
> +{
> +    HotplugHandler *hotplug_ctrl;
> +    PCIDevice *pdev = PCI_DEVICE(n->primary_dev);
> +
> +    if (!pdev->partially_hotplugged) {
> +        return true;
> +    }
> +    if (!n->primary_device_opts) {
> +        n->primary_device_opts = qemu_opts_from_qdict(
> +                qemu_find_opts("device"),
> +                n->primary_device_dict, errp);
> +    }
> +    if (n->primary_device_opts) {
> +        if (n->primary_dev) {

Here we check whether n->primary_dev is NULL...

> +            n->primary_bus = n->primary_dev->parent_bus;
> +        }
> +        qdev_set_parent_bus(n->primary_dev, n->primary_bus);

...but qdev_set_parent_bus unconditionally dereferences
its first argument, so it can't be NULL...

> +        n->primary_should_be_hidden = false;
> +        qemu_opt_set_bool(n->primary_device_opts,
> +                "partially_hotplugged", true, errp);
> +        hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev);
> +        if (hotplug_ctrl) {
> +            hotplug_handler_pre_plug(hotplug_ctrl, n->primary_dev, errp);
> +            hotplug_handler_plug(hotplug_ctrl, n->primary_dev, errp);
> +        }
> +        if (!n->primary_dev) {

...and we do another NULL check here.

Either we don't need the NULL checks, or we need to avoid
calling qdev_set_parent_bus(NULL, ...).

(This is CID 1407224.)

> +            error_setg(errp, "virtio_net: couldn't find primary device");
> +        }
> +    }
> +    return *errp != NULL;
> +}


> +static int virtio_net_primary_should_be_hidden(DeviceListener *listener,
> +            QemuOpts *device_opts)
> +{
> +    VirtIONet *n = container_of(listener, VirtIONet, primary_listener);
> +    bool match_found;
> +    bool hide;
> +
> +    n->primary_device_dict = qemu_opts_to_qdict(device_opts,
> +            n->primary_device_dict);

Here we pass device_optns to qemu_opts_to_qdict(), which must
take a non-NULL pointer (it always dereferences it)...

> +    if (n->primary_device_dict) {
> +        g_free(n->standby_id);
> +        n->standby_id = g_strdup(qdict_get_try_str(n->primary_device_dict,
> +                    "failover_pair_id"));
> +    }
> +    if (device_opts && g_strcmp0(n->standby_id, n->netclient_name) == 0) {

...but here we check whether device_opts is NULL.

Again, either the check or the call must be wrong.

(This is CID 1407222.)

> +        match_found = true;
> +    } else {
> +        match_found = false;
> +        hide = false;
> +        g_free(n->standby_id);
> +        n->primary_device_dict = NULL;
> +        goto out;
> +    }

thanks
-- PMM

Reply via email to