qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-stable@nongnu.org, qemu-devel@nongnu.org, afaerber@suse.de
Subject: Re: [Qemu-devel] [PATCH 2/2] qdev: recursively unrealize devices when unrealizing bus
Date: Wed, 11 Jun 2014 16:57:15 +0300	[thread overview]
Message-ID: <20140611135715.GA8362@redhat.com> (raw)
In-Reply-To: <1402491129-21933-3-git-send-email-pbonzini@redhat.com>

On Wed, Jun 11, 2014 at 02:52:09PM +0200, Paolo Bonzini wrote:
> When the patch was posted that became 5c21ce7 (qdev: Realize buses
> on device realization, 2014-03-12), it included recursive realization
> and unrealization of devices when the bus's "realized" property
> was toggled.
> 
> However, due to the same old worries about recursive realization
> and prerequisites not being realized yet, those hunks were dropped when
> committing the patch.  Unfortunately, this causes a use-after-free bug
> (easily reproduced by a PCI hot-unplug action).
> 
> Before the patch, device_unparent behaved as follows:
> 
>    for each child bus
>      unparent bus ----------------------------.
>      | for each child device                  |
>      |   unparent device ---------------.     |
>      |   | unrealize device             |     |
>      |   | call dc->unparent            |     |
>      |   '-------------------------------     |
>      '----------------------------------------'
>    unrealize device
> 
> After the patch, it behaves as follows instead:
> 
>    unrealize device --------------------.
>    | for each child bus                 |
>    |   unrealize bus               (A)  |
>    '------------------------------------'
>    for each child bus
>      unparent bus ----------------------.
>      | for each child device            |
>      |   unrealize device          (B)  |
>      |   call dc->unparent              |
>      '----------------------------------'
> 
> At the step marked (B) the device might use data from the bus that is
> not available anymore due to step (A).
> 
> To fix this, we need to unrealize devices before step (A).  To sidestep
> concerns about recursive realization, only do recursive unrealization
> and leave the "value && !bus->realized" case as it is.
> 
> The resulting flow is:
> 
>    for each child bus
>      unrealize bus ---------------------.
>      | for each child device            |
>      |   unrealize device          (B)  |
>      | call bc->unrealize          (A)  |
>      '----------------------------------'
>    unrealize device
>    for each child bus
>      unparent bus ----------------------.
>      | for each child device            |
>      |   unparent device                |
>      '----------------------------------'
> 
> where everything is "powered down" before it is unassembled.

functionality-wise, patch looks good to me.

Reviewed-by: Michael S. Tsirkin <mst@redhat.com>

object_unparent is called in many places, we really
should have some documentation for this API.

> Cc: qemu-stable@nongnu.org
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/core/qdev.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 5efa251..4282491 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -567,14 +567,25 @@ static void bus_set_realized(Object *obj, bool value, Error **errp)
>  {
>      BusState *bus = BUS(obj);
>      BusClass *bc = BUS_GET_CLASS(bus);
> +    BusChild *kid;
>      Error *local_err = NULL;
>  
>      if (value && !bus->realized) {
>          if (bc->realize) {
>              bc->realize(bus, &local_err);
>          }
> +
> +        /* TODO: recursive realization */
>      } else if (!value && bus->realized) {
> -        if (bc->unrealize) {
> +        QTAILQ_FOREACH(kid, &bus->children, sibling) {
> +            DeviceState *dev = kid->child;
> +            object_property_set_bool(OBJECT(dev), false, "realized",
> +                                     &local_err);
> +            if (local_err != NULL) {
> +                break;
> +            }
> +        }
> +        if (bc->unrealize && local_err == NULL) {
>              bc->unrealize(bus, &local_err);
>          }
>      }
> -- 
> 1.8.3.1

  reply	other threads:[~2014-06-11 13:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-11 12:52 [Qemu-devel] [PATCH 0/2] qdev: fix pci use-after-free Paolo Bonzini
2014-06-11 12:52 ` [Qemu-devel] [PATCH 1/2] qdev: reorganize error reporting in bus_set_realized Paolo Bonzini
2014-06-11 12:52 ` [Qemu-devel] [PATCH 2/2] qdev: recursively unrealize devices when unrealizing bus Paolo Bonzini
2014-06-11 13:57   ` Michael S. Tsirkin [this message]
2014-06-26 12:34   ` Markus Armbruster
2014-06-15 10:02 ` [Qemu-devel] [PATCH 0/2] qdev: fix pci use-after-free Michael S. Tsirkin
2014-06-15 11:42   ` Andreas Färber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140611135715.GA8362@redhat.com \
    --to=mst@redhat.com \
    --cc=afaerber@suse.de \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).