|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 1/2] Fix use-after-free in evtchn DPC
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |