All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] 9p: fix guest-triggered Treaddir/ACPI eject UAF
@ 2026-07-18 16:50 Christian Schoenebeck
  2026-07-18 16:50 ` [PATCH v2 1/2] hw/9pfs/virtio: drain in-flight PDUs before virtio-9p unrealize Christian Schoenebeck
  2026-07-18 16:50 ` [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect Christian Schoenebeck
  0 siblings, 2 replies; 6+ messages in thread
From: Christian Schoenebeck @ 2026-07-18 16:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-stable, Greg Kurz, Stefano Stabellini, Anthony PERARD,
	Edgar E. Iglesias, Jia Jia

A guest can trigger unplugging 9pfs server's virtio-pci device via ACPI
eject. As a consequence the device is unrealized, server's internal state
is freed while pending coroutines would still have access to them, causing
a potential heap-use-after-free.

Overview Patches:

 - Patch 1: this is the core fix, that drains all PDUs (i.e. coroutines
   that handle individual pending requests in parallel) before freeing
   server state.

 - Patch 2: fixes a similar identified issue with the Xen transport, even
   though not triggered via ACPI, it is also prone to UAF, plus a resource
   leak.

v2:
  - Patch 1: Make Jia the official author of this patch.
  - Drop prev. patch 2 ("hw/9pfs/virtio: disable hotpluggable property...")
  - Patch 2: defer explict xen_9pfs_disconnect() call from error paths of
    xen_9pfs_pdu_vmarshal() and xen_9pfs_pdu_vunmarshal().

Christian Schoenebeck (1):
  hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect

Jia Jia (1):
  hw/9pfs/virtio: drain in-flight PDUs before virtio-9p unrealize

 hw/9pfs/virtio-9p-device.c |  1 +
 hw/9pfs/xen-9p-backend.c   | 19 +++++++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

-- 
2.47.3



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/2] hw/9pfs/virtio: drain in-flight PDUs before virtio-9p unrealize
  2026-07-18 16:50 [PATCH v2 0/2] 9p: fix guest-triggered Treaddir/ACPI eject UAF Christian Schoenebeck
@ 2026-07-18 16:50 ` Christian Schoenebeck
  2026-07-18 16:50 ` [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect Christian Schoenebeck
  1 sibling, 0 replies; 6+ messages in thread
From: Christian Schoenebeck @ 2026-07-18 16:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Greg Kurz, Jia Jia

From: Jia Jia <physicalmtea@gmail.com>

A guest can trigger a heap-use-after-free in the virtio transport
unrealize path by submitting a Treaddir request and immediately
ejecting the device via ACPI PCI hotplug. The unrealize path frees
struct LocalData while a worker thread still holds a reference
on it, causing a UAF in local_open_nofollow().

Fix this by draining all in-flight 9p PDUs by calling v9fs_reset()
before final server cleanup. This ensures all coroutines completed,
all FIDs are closed, and no worker thread still holds references
on 9p server state when it is freed.

Fixes: 6cecf09373 ("virtio-9p-device: add minimal unrealize handler")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3937
Signed-off-by: Jia Jia <physicalmtea@gmail.com>
[ Christian Schoenebeck: add commit log message. ]
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
 hw/9pfs/virtio-9p-device.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 50dc93091d..1ec48fc9e0 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -243,6 +243,7 @@ static void virtio_9p_device_unrealize(DeviceState *dev)
     V9fsVirtioState *v = VIRTIO_9P(dev);
     V9fsState *s = &v->state;
 
+    v9fs_reset(s);
     virtio_delete_queue(v->vq);
     virtio_cleanup(vdev);
     v9fs_device_unrealize_common(s);
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect
  2026-07-18 16:50 [PATCH v2 0/2] 9p: fix guest-triggered Treaddir/ACPI eject UAF Christian Schoenebeck
  2026-07-18 16:50 ` [PATCH v2 1/2] hw/9pfs/virtio: drain in-flight PDUs before virtio-9p unrealize Christian Schoenebeck
@ 2026-07-18 16:50 ` Christian Schoenebeck
  2026-07-22  9:27   ` Christian Schoenebeck
  1 sibling, 1 reply; 6+ messages in thread
From: Christian Schoenebeck @ 2026-07-18 16:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-stable, Greg Kurz, Stefano Stabellini, Anthony PERARD,
	Edgar E. Iglesias

The xen-9p disconnect path has two issues:

1. It frees the Xen9pfsRing structures while in-flight PDUs may still
   reference them via pdu->tag to index rings[]. This causes a UAF
   in xen_9pfs_push_and_notify() when worker threads resume after
   completing filesystem operations.

2. It never calls v9fs_device_unrealize_common(), which means server
   state (struct LocalData, mountfd, FIDs) is never cleaned up on
   disconnect, causing a resource leak on every guest-initiated
   disconnect.

Fix both by draining in-flight PDUs via v9fs_reset() before tearing
down rings, and calling v9fs_device_unrealize_common() to clean up
server state.

Additionally, explicit calls of xen_9pfs_disconnect() in the error
paths of xen_9pfs_pdu_vmarshal() and xen_9pfs_pdu_vunmarshal() must
be deferred (via aio_bh_schedule_oneshot()), because
xen_9pfs_pdu_v(un)marshal() are running within a coroutine context
which makes them unsafe [1] for calling v9fs_reset() directly, as
the latter e.g. has a loop like:

    while (!QLIST_EMPTY(&s->active_list)) {
        aio_poll(qemu_get_aio_context(), true);
    }

which would a) never terminate (as the coroutine is on the
active_list) and b) aio_poll() is marked as no_coroutine_fn.

[1] https://lore.kernel.org/qemu-devel/3351181.5fSG56mABF@weasel/

And finally, add an idempotent guard to xen_9pfs_disconnect(),
just for the case.

Fixes: b37eeb0201 ("xen/9pfs: introduce Xen 9pfs backend")
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
 hw/9pfs/xen-9p-backend.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index 24c90d97ec..edb65a7afc 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -68,6 +68,11 @@ typedef struct Xen9pfsDev {
 
 static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev);
 
+static void xen_9pfs_disconnect_bh(void *opaque)
+{
+    xen_9pfs_disconnect(opaque);
+}
+
 static void xen_9pfs_in_sg(Xen9pfsRing *ring,
                            struct iovec *in_sg,
                            int *num,
@@ -150,7 +155,8 @@ static ssize_t xen_9pfs_pdu_vmarshal(V9fsPDU *pdu,
                       "Failed to encode VirtFS reply type %d\n",
                       pdu->id + 1);
         xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
-        xen_9pfs_disconnect(&xen_9pfs->xendev);
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                xen_9pfs_disconnect_bh, &xen_9pfs->xendev);
     }
     return ret;
 }
@@ -173,7 +179,8 @@ static ssize_t xen_9pfs_pdu_vunmarshal(V9fsPDU *pdu,
         xen_pv_printf(&xen_9pfs->xendev, 0,
                       "Failed to decode VirtFS request type %d\n", pdu->id);
         xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
-        xen_9pfs_disconnect(&xen_9pfs->xendev);
+        aio_bh_schedule_oneshot(qemu_get_aio_context(),
+                                xen_9pfs_disconnect_bh, &xen_9pfs->xendev);
     }
     return ret;
 }
@@ -368,10 +375,18 @@ static void xen_9pfs_evtchn_event(void *opaque)
 static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
 {
     Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
+    V9fsState *s = &xen_9pdev->state;
     int i;
 
+    if (!xen_9pdev->rings) {
+        return;
+    }
+
     trace_xen_9pfs_disconnect(xendev->name);
 
+    v9fs_reset(s);
+    v9fs_device_unrealize_common(s);
+
     for (i = 0; i < xen_9pdev->num_rings; i++) {
         if (xen_9pdev->rings[i].evtchndev != NULL) {
             qemu_set_fd_handler(qemu_xen_evtchn_fd(xen_9pdev->rings[i].evtchndev),
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect
  2026-07-18 16:50 ` [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect Christian Schoenebeck
@ 2026-07-22  9:27   ` Christian Schoenebeck
  2026-07-23  1:17     ` Stefano Stabellini
  0 siblings, 1 reply; 6+ messages in thread
From: Christian Schoenebeck @ 2026-07-22  9:27 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: qemu-devel, qemu-stable, Greg Kurz, Anthony PERARD,
	Edgar E. Iglesias

Hi Stefano,

chance that you might be looking at this v2 Xen patch soon? If not, just let 
me know, then I'll send out a PR with other fixes piled up on my side in the 
meantime, as QEMU release window narrows.

/Christian 

On Saturday, 18 July 2026 18:50:06 CEST Christian Schoenebeck wrote:
> The xen-9p disconnect path has two issues:
> 
> 1. It frees the Xen9pfsRing structures while in-flight PDUs may still
>    reference them via pdu->tag to index rings[]. This causes a UAF
>    in xen_9pfs_push_and_notify() when worker threads resume after
>    completing filesystem operations.
> 
> 2. It never calls v9fs_device_unrealize_common(), which means server
>    state (struct LocalData, mountfd, FIDs) is never cleaned up on
>    disconnect, causing a resource leak on every guest-initiated
>    disconnect.
> 
> Fix both by draining in-flight PDUs via v9fs_reset() before tearing
> down rings, and calling v9fs_device_unrealize_common() to clean up
> server state.
> 
> Additionally, explicit calls of xen_9pfs_disconnect() in the error
> paths of xen_9pfs_pdu_vmarshal() and xen_9pfs_pdu_vunmarshal() must
> be deferred (via aio_bh_schedule_oneshot()), because
> xen_9pfs_pdu_v(un)marshal() are running within a coroutine context
> which makes them unsafe [1] for calling v9fs_reset() directly, as
> the latter e.g. has a loop like:
> 
>     while (!QLIST_EMPTY(&s->active_list)) {
>         aio_poll(qemu_get_aio_context(), true);
>     }
> 
> which would a) never terminate (as the coroutine is on the
> active_list) and b) aio_poll() is marked as no_coroutine_fn.
> 
> [1] https://lore.kernel.org/qemu-devel/3351181.5fSG56mABF@weasel/
> 
> And finally, add an idempotent guard to xen_9pfs_disconnect(),
> just for the case.
> 
> Fixes: b37eeb0201 ("xen/9pfs: introduce Xen 9pfs backend")
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---
>  hw/9pfs/xen-9p-backend.c | 19 +++++++++++++++++--
>  1 file changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
> index 24c90d97ec..edb65a7afc 100644
> --- a/hw/9pfs/xen-9p-backend.c
> +++ b/hw/9pfs/xen-9p-backend.c
> @@ -68,6 +68,11 @@ typedef struct Xen9pfsDev {
> 
>  static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev);
> 
> +static void xen_9pfs_disconnect_bh(void *opaque)
> +{
> +    xen_9pfs_disconnect(opaque);
> +}
> +
>  static void xen_9pfs_in_sg(Xen9pfsRing *ring,
>                             struct iovec *in_sg,
>                             int *num,
> @@ -150,7 +155,8 @@ static ssize_t xen_9pfs_pdu_vmarshal(V9fsPDU *pdu,
>                        "Failed to encode VirtFS reply type %d\n",
>                        pdu->id + 1);
>          xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
> -        xen_9pfs_disconnect(&xen_9pfs->xendev);
> +        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> +                                xen_9pfs_disconnect_bh, &xen_9pfs->xendev);
> }
>      return ret;
>  }
> @@ -173,7 +179,8 @@ static ssize_t xen_9pfs_pdu_vunmarshal(V9fsPDU *pdu,
>          xen_pv_printf(&xen_9pfs->xendev, 0,
>                        "Failed to decode VirtFS request type %d\n",
> pdu->id); xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
> -        xen_9pfs_disconnect(&xen_9pfs->xendev);
> +        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> +                                xen_9pfs_disconnect_bh, &xen_9pfs->xendev);
> }
>      return ret;
>  }
> @@ -368,10 +375,18 @@ static void xen_9pfs_evtchn_event(void *opaque)
>  static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
>  {
>      Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
> +    V9fsState *s = &xen_9pdev->state;
>      int i;
> 
> +    if (!xen_9pdev->rings) {
> +        return;
> +    }
> +
>      trace_xen_9pfs_disconnect(xendev->name);
> 
> +    v9fs_reset(s);
> +    v9fs_device_unrealize_common(s);
> +
>      for (i = 0; i < xen_9pdev->num_rings; i++) {
>          if (xen_9pdev->rings[i].evtchndev != NULL) {
>             
> qemu_set_fd_handler(qemu_xen_evtchn_fd(xen_9pdev->rings[i].evtchndev),






^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect
  2026-07-22  9:27   ` Christian Schoenebeck
@ 2026-07-23  1:17     ` Stefano Stabellini
  2026-07-23 11:20       ` Christian Schoenebeck
  0 siblings, 1 reply; 6+ messages in thread
From: Stefano Stabellini @ 2026-07-23  1:17 UTC (permalink / raw)
  To: Christian Schoenebeck
  Cc: Stefano Stabellini, qemu-devel, qemu-stable, Greg Kurz,
	Anthony PERARD, Edgar E. Iglesias

On Wed, 22 Jul 2026, Christian Schoenebeck wrote:
> Hi Stefano,
> 
> chance that you might be looking at this v2 Xen patch soon? If not, just let 
> me know, then I'll send out a PR with other fixes piled up on my side in the 
> meantime, as QEMU release window narrows.

This is better but I think there is still an issue

 
> On Saturday, 18 July 2026 18:50:06 CEST Christian Schoenebeck wrote:
> > The xen-9p disconnect path has two issues:
> > 
> > 1. It frees the Xen9pfsRing structures while in-flight PDUs may still
> >    reference them via pdu->tag to index rings[]. This causes a UAF
> >    in xen_9pfs_push_and_notify() when worker threads resume after
> >    completing filesystem operations.
> > 
> > 2. It never calls v9fs_device_unrealize_common(), which means server
> >    state (struct LocalData, mountfd, FIDs) is never cleaned up on
> >    disconnect, causing a resource leak on every guest-initiated
> >    disconnect.
> > 
> > Fix both by draining in-flight PDUs via v9fs_reset() before tearing
> > down rings, and calling v9fs_device_unrealize_common() to clean up
> > server state.
> > 
> > Additionally, explicit calls of xen_9pfs_disconnect() in the error
> > paths of xen_9pfs_pdu_vmarshal() and xen_9pfs_pdu_vunmarshal() must
> > be deferred (via aio_bh_schedule_oneshot()), because
> > xen_9pfs_pdu_v(un)marshal() are running within a coroutine context
> > which makes them unsafe [1] for calling v9fs_reset() directly, as
> > the latter e.g. has a loop like:
> > 
> >     while (!QLIST_EMPTY(&s->active_list)) {
> >         aio_poll(qemu_get_aio_context(), true);
> >     }
> > 
> > which would a) never terminate (as the coroutine is on the
> > active_list) and b) aio_poll() is marked as no_coroutine_fn.
> > 
> > [1] https://lore.kernel.org/qemu-devel/3351181.5fSG56mABF@weasel/
> > 
> > And finally, add an idempotent guard to xen_9pfs_disconnect(),
> > just for the case.
> > 
> > Fixes: b37eeb0201 ("xen/9pfs: introduce Xen 9pfs backend")
> > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > ---
> >  hw/9pfs/xen-9p-backend.c | 19 +++++++++++++++++--
> >  1 file changed, 17 insertions(+), 2 deletions(-)
> > 
> > diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
> > index 24c90d97ec..edb65a7afc 100644
> > --- a/hw/9pfs/xen-9p-backend.c
> > +++ b/hw/9pfs/xen-9p-backend.c
> > @@ -68,6 +68,11 @@ typedef struct Xen9pfsDev {
> > 
> >  static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev);
> > 
> > +static void xen_9pfs_disconnect_bh(void *opaque)
> > +{
> > +    xen_9pfs_disconnect(opaque);
> > +}
> > +
> >  static void xen_9pfs_in_sg(Xen9pfsRing *ring,
> >                             struct iovec *in_sg,
> >                             int *num,
> > @@ -150,7 +155,8 @@ static ssize_t xen_9pfs_pdu_vmarshal(V9fsPDU *pdu,
> >                        "Failed to encode VirtFS reply type %d\n",
> >                        pdu->id + 1);
> >          xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
> > -        xen_9pfs_disconnect(&xen_9pfs->xendev);
> > +        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> > +                                xen_9pfs_disconnect_bh, &xen_9pfs->xendev);
> > }
> >      return ret;
> >  }
> > @@ -173,7 +179,8 @@ static ssize_t xen_9pfs_pdu_vunmarshal(V9fsPDU *pdu,
> >          xen_pv_printf(&xen_9pfs->xendev, 0,
> >                        "Failed to decode VirtFS request type %d\n",
> > pdu->id); xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
> > -        xen_9pfs_disconnect(&xen_9pfs->xendev);
> > +        aio_bh_schedule_oneshot(qemu_get_aio_context(),
> > +                                xen_9pfs_disconnect_bh, &xen_9pfs->xendev);
> > }
> >      return ret;
> >  }
> > @@ -368,10 +375,18 @@ static void xen_9pfs_evtchn_event(void *opaque)
> >  static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
> >  {
> >      Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
> > +    V9fsState *s = &xen_9pdev->state;
> >      int i;
> > 
> > +    if (!xen_9pdev->rings) {

specifically this check is not sufficient are there can be cases where
rings != NULL but transport is not set and v9fs_reset should not be
called. For instance xen_be_map_grant_ref() returns NULL,
xen_9pfs_connect() go out without calling v9fs_device_realize_common().
s->transport == NULL and also s->fids == NULL but rings != NULL. Later
v9fs_reset calls g_hash_table_get_values(s->fids)



> > +        return;
> > +    }
> > +
> >      trace_xen_9pfs_disconnect(xendev->name);
> > 
> > +    v9fs_reset(s);
> > +    v9fs_device_unrealize_common(s);
> > +
> >      for (i = 0; i < xen_9pdev->num_rings; i++) {
> >          if (xen_9pdev->rings[i].evtchndev != NULL) {
> >             
> > qemu_set_fd_handler(qemu_xen_evtchn_fd(xen_9pdev->rings[i].evtchndev),

See this below. If you agree and add the below to this patch you can add
my Reviewed-by.


diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 3119f01117..fc01791830 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -4530,6 +4530,7 @@ void v9fs_device_unrealize_common(V9fsState *s)
     qp_table_destroy(&s->qpp_table);
     qp_table_destroy(&s->qpf_table);
     g_free(s->ctx.fs_root);
+    s->transport = NULL;
 }
 
 typedef struct VirtfsCoResetData {
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index edb65a7afc..f0791f9e97 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -384,8 +384,10 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
 
     trace_xen_9pfs_disconnect(xendev->name);
 
-    v9fs_reset(s);
-    v9fs_device_unrealize_common(s);
+    if (s->transport) {
+        v9fs_reset(s);
+        v9fs_device_unrealize_common(s);
+    }
 
     for (i = 0; i < xen_9pdev->num_rings; i++) {
         if (xen_9pdev->rings[i].evtchndev != NULL) {


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect
  2026-07-23  1:17     ` Stefano Stabellini
@ 2026-07-23 11:20       ` Christian Schoenebeck
  0 siblings, 0 replies; 6+ messages in thread
From: Christian Schoenebeck @ 2026-07-23 11:20 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: qemu-devel, qemu-stable, Greg Kurz, Anthony PERARD,
	Edgar E. Iglesias

On Thursday, 23 July 2026 03:17:12 CEST Stefano Stabellini wrote:
> On Wed, 22 Jul 2026, Christian Schoenebeck wrote:
[...]
> > > @@ -368,10 +375,18 @@ static void xen_9pfs_evtchn_event(void *opaque)
> > > 
> > >  static void xen_9pfs_disconnect(struct XenLegacyDevice *xendev)
> > >  {
> > >  
> > >      Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
> > > 
> > > +    V9fsState *s = &xen_9pdev->state;
> > > 
> > >      int i;
> > > 
> > > +    if (!xen_9pdev->rings) {
> 
> specifically this check is not sufficient are there can be cases where
> rings != NULL but transport is not set and v9fs_reset should not be
> called. For instance xen_be_map_grant_ref() returns NULL,
> xen_9pfs_connect() go out without calling v9fs_device_realize_common().
> s->transport == NULL and also s->fids == NULL but rings != NULL. Later
> v9fs_reset calls g_hash_table_get_values(s->fids)
> 
> > > +        return;
> > > +    }
> > > +
> > > 
> > >      trace_xen_9pfs_disconnect(xendev->name);
> > > 
> > > +    v9fs_reset(s);
> > > +    v9fs_device_unrealize_common(s);
> > > +
> > > 
> > >      for (i = 0; i < xen_9pdev->num_rings; i++) {
> > >      
> > >          if (xen_9pdev->rings[i].evtchndev != NULL) {
> > > 
> > > qemu_set_fd_handler(qemu_xen_evtchn_fd(xen_9pdev->rings[i].evtchndev),
> 
> See this below. If you agree and add the below to this patch you can add
> my Reviewed-by.
> 
> 
> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> index 3119f01117..fc01791830 100644
> --- a/hw/9pfs/9p.c
> +++ b/hw/9pfs/9p.c
> @@ -4530,6 +4530,7 @@ void v9fs_device_unrealize_common(V9fsState *s)
>      qp_table_destroy(&s->qpp_table);
>      qp_table_destroy(&s->qpf_table);
>      g_free(s->ctx.fs_root);
> +    s->transport = NULL;
>  }
> 
>  typedef struct VirtfsCoResetData {
> diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
> index edb65a7afc..f0791f9e97 100644
> --- a/hw/9pfs/xen-9p-backend.c
> +++ b/hw/9pfs/xen-9p-backend.c
> @@ -384,8 +384,10 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice
> *xendev)
> 
>      trace_xen_9pfs_disconnect(xendev->name);
> 
> -    v9fs_reset(s);
> -    v9fs_device_unrealize_common(s);
> +    if (s->transport) {
> +        v9fs_reset(s);
> +        v9fs_device_unrealize_common(s);
> +    }
> 
>      for (i = 0; i < xen_9pdev->num_rings; i++) {
>          if (xen_9pdev->rings[i].evtchndev != NULL) {

Agreed, these two changes makes sense. I'll formally send a v3 with these two 
changes added now.

My plan is to send a PR with this and other fixes tomorrow already, as we're 
getting very close to release.

Thanks Stefano!

/Christian




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-07-23 11:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-18 16:50 [PATCH v2 0/2] 9p: fix guest-triggered Treaddir/ACPI eject UAF Christian Schoenebeck
2026-07-18 16:50 ` [PATCH v2 1/2] hw/9pfs/virtio: drain in-flight PDUs before virtio-9p unrealize Christian Schoenebeck
2026-07-18 16:50 ` [PATCH v2 2/2] hw/9pfs/xen: drain in-flight PDUs before xen-9p disconnect Christian Schoenebeck
2026-07-22  9:27   ` Christian Schoenebeck
2026-07-23  1:17     ` Stefano Stabellini
2026-07-23 11:20       ` Christian Schoenebeck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.