[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] Fix use-after-free in evtchn DPC


  • To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Rafał Wojdyła <omeg@xxxxxxxxxxxxxxxxxxxxxx>
  • Date: Tue, 26 May 2026 18:29:33 +0200
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=fm3 header.d=invisiblethingslab.com header.i="@invisiblethingslab.com" header.h="Cc:Content-Transfer-Encoding:Content-Type:Date:From:In-Reply-To:Message-ID:MIME-Version:References:Subject:To"; dkim=pass header.s=fm3 header.d=messagingengine.com header.i="@messagingengine.com" header.h="Cc:Content-Transfer-Encoding:Content-Type:Date:Feedback-ID:From:In-Reply-To:Message-ID:MIME-Version:References:Subject:To:X-ME-Proxy:X-ME-Sender"
  • Cc: Rafał Wojdyła <omeg@xxxxxxxxxxxxxxxxxxxxxx>
  • Delivery-date: Tue, 26 May 2026 16:29:53 +0000
  • Feedback-id: i409c4082:Fastmail
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

EvtchnFree() calls XENBUS_EVTCHN(Close) and then KeFlushQueuedDpcs()
to drain any pending DPCs. A DPC queued just before Close returns can
run in the window between Close completing and the flush draining it,
at which point it dereferences Context->Channel inside
XENBUS_EVTCHN(Unmask).

Also move Context->Fdo initialization to before opening the channel
so Context is fully populated by the time the channel can fire its first
interrupt.

Signed-off-by: Rafał Wojdyła <omeg@xxxxxxxxxxxxxxxxxxxxxx>
---
 src/xeniface/ioctl_evtchn.c | 21 ++++++++++++++-------
 src/xeniface/ioctls.h       |  1 +
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/src/xeniface/ioctl_evtchn.c b/src/xeniface/ioctl_evtchn.c
index 6d63996..e38e25f 100644
--- a/src/xeniface/ioctl_evtchn.c
+++ b/src/xeniface/ioctl_evtchn.c
@@ -58,11 +58,14 @@ EvtchnNotificationDpc(
 
     KeSetEvent(Context->Event, 0, FALSE);
 
-    (VOID) XENBUS_EVTCHN(Unmask,
-                         &Context->Fdo->EvtchnInterface,
-                         Context->Channel,
-                         FALSE,
-                         TRUE);
+    if (InterlockedCompareExchange(&Context->Ready, 1, 1) == 1) {
+        (VOID) XENBUS_EVTCHN(Unmask,
+                             &Context->Fdo->EvtchnInterface,
+                             Context->Channel,
+                             FALSE,
+                             TRUE);
+
+    }
 }
 
 _Function_class_(KSERVICE_ROUTINE)
@@ -103,6 +106,8 @@ EvtchnFree(
     Trace("Context %p, LocalPort %d, FO %p\n",
                        Context, Context->LocalPort, Context->FileObject);
 
+    (VOID) InterlockedExchange(&Context->Ready, 0);
+
     XENBUS_EVTCHN(Close,
                   &Fdo->EvtchnInterface,
                   Context->Channel);
@@ -176,6 +181,7 @@ IoctlEvtchnBindUnbound(
         goto fail2;
 
     Context->FileObject = FileObject;
+    Context->Fdo = Fdo;
 
     Trace("> RemoteDomain %d, Mask %d, FO %p\n",
                        In->RemoteDomain, In->Mask, FileObject);
@@ -206,7 +212,7 @@ IoctlEvtchnBindUnbound(
                                        &Fdo->EvtchnInterface,
                                        Context->Channel);
 
-    Context->Fdo = Fdo;
+    (VOID) InterlockedExchange(&Context->Ready, 1);
 
     ExInterlockedInsertTailList(&Fdo->EvtchnList, &Context->Entry, 
&Fdo->EvtchnLock);
 
@@ -269,6 +275,7 @@ IoctlEvtchnBindInterdomain(
         goto fail2;
 
     Context->FileObject = FileObject;
+    Context->Fdo = Fdo;
 
     Trace("> RemoteDomain %d, RemotePort %lu, Mask %d, FO %p\n",
                        In->RemoteDomain, In->RemotePort, In->Mask, FileObject);
@@ -300,7 +307,7 @@ IoctlEvtchnBindInterdomain(
                                        &Fdo->EvtchnInterface,
                                        Context->Channel);
 
-    Context->Fdo = Fdo;
+    (VOID) InterlockedExchange(&Context->Ready, 1);
 
     ExInterlockedInsertTailList(&Fdo->EvtchnList, &Context->Entry, 
&Fdo->EvtchnLock);
 
diff --git a/src/xeniface/ioctls.h b/src/xeniface/ioctls.h
index b4c8de2..f5eddbf 100644
--- a/src/xeniface/ioctls.h
+++ b/src/xeniface/ioctls.h
@@ -53,6 +53,7 @@ typedef struct _XENIFACE_EVTCHN_CONTEXT {
     PXENIFACE_FDO          Fdo;
     KDPC                   Dpc;
     PVOID                  FileObject;
+    volatile LONG          Ready;
 } XENIFACE_EVTCHN_CONTEXT, *PXENIFACE_EVTCHN_CONTEXT;
 
 typedef struct _XENIFACE_SUSPEND_CONTEXT {
-- 
2.53.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.