Skip to content

Commit

Permalink
qdev: Fix object reference leak in case device.realize() fails
Browse files Browse the repository at this point in the history
If device doesn't have parent assined before its realize
is called, device_set_realized() will implicitly set parent
to '/machine/unattached'.

However device_set_realized() may fail after that point at
several other points leaving not realized object dangling
in '/machine/unattached' and as result caller of

  obj = object_new()
    obj->ref == 1
  object_property_set_bool(obj,..., true, "realized",...)
    obj->ref == 2
  if (fail)
      object_unref(obj);
      obj->ref == 1

will get object leak instead of expected object destruction.

Fix it by making device_set_realized() to cleanup after itself
in case of failure.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
  • Loading branch information
Igor Mammedov authored and ehabkost committed Jul 26, 2016
1 parent a07f953 commit 69382d8
Showing 1 changed file with 7 additions and 1 deletion.
8 changes: 7 additions & 1 deletion hw/core/qdev.c
Expand Up @@ -885,6 +885,8 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
HotplugHandler *hotplug_ctrl;
BusState *bus;
Error *local_err = NULL;
bool unattached_parent = false;
static int unattached_count;

if (dev->hotplugged && !dc->hotpluggable) {
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
Expand All @@ -893,12 +895,12 @@ static void device_set_realized(Object *obj, bool value, Error **errp)

if (value && !dev->realized) {
if (!obj->parent) {
static int unattached_count;
gchar *name = g_strdup_printf("device[%d]", unattached_count++);

object_property_add_child(container_get(qdev_get_machine(),
"/unattached"),
name, obj, &error_abort);
unattached_parent = true;
g_free(name);
}

Expand Down Expand Up @@ -987,6 +989,10 @@ static void device_set_realized(Object *obj, bool value, Error **errp)

fail:
error_propagate(errp, local_err);
if (unattached_parent) {
object_unparent(OBJECT(dev));
unattached_count--;
}
}

static bool device_get_hotpluggable(Object *obj, Error **errp)
Expand Down

0 comments on commit 69382d8

Please sign in to comment.