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

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


  • To: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>, win-pv-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Rafał Wojdyła <omeg@xxxxxxxxxxxxxxxxxxxxxx>
  • Date: Wed, 27 May 2026 10:59:52 +0200
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=fm3 header.d=invisiblethingslab.com header.i="@invisiblethingslab.com" header.h="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="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"
  • Delivery-date: Wed, 27 May 2026 09:00:02 +0000
  • Feedback-id: i409c4082:Fastmail
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>



W dniu 27.05.2026 o 03:41, Tu Dinh pisze:
On 26/05/2026 18:30, Rafał Wojdyła wrote:
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);
+

Shouldn't KeFlushQueuedDpcs() be called before closing the channel?
Otherwise there could still be a DPC which has captured Context->Ready=1
before InterlockedExchange is called, and then still running
concurrently with the XENBUS_EVTCHN(Close).
From my understanding KeFlushQueuedDpcs() flushes what's *currently* queued, so there would still be a window after it completes and before Close() finishes when new events could arrive.



 


Rackspace

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