https://git.reactos.org/?p=reactos.git;a=commitdiff;h=176de8bd256c2774676b5…
commit 176de8bd256c2774676b527906f8bdb1350fb34f
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Wed Oct 9 13:21:29 2024 +0200
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Thu Oct 10 20:28:59 2024 +0300
[NTOS:PNP] Don't use a pointer to a stack structure in a work-item
Previously FsRtlNotifyVolumeEvent would pass a pointer to a TARGET_DEVICE_CUSTOM_NOTIFICATION structure on the stack to IoReportTargetDeviceChangeAsynchronous, which would store a pointer to it in a work-item and process that after the stack object was already out of scope. This broke x64 boot. Started happening after recent fixes to IoReportTargetDeviceChangeAsynchronous.
---
ntoskrnl/io/pnpmgr/pnpreport.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/ntoskrnl/io/pnpmgr/pnpreport.c b/ntoskrnl/io/pnpmgr/pnpreport.c
index ea23aa13304..09279b7ef6f 100644
--- a/ntoskrnl/io/pnpmgr/pnpreport.c
+++ b/ntoskrnl/io/pnpmgr/pnpreport.c
@@ -21,7 +21,7 @@ typedef struct _INTERNAL_WORK_QUEUE_ITEM
PDEVICE_OBJECT PhysicalDeviceObject;
PDEVICE_CHANGE_COMPLETE_CALLBACK Callback;
PVOID Context;
- PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure;
+ TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure;
} INTERNAL_WORK_QUEUE_ITEM, *PINTERNAL_WORK_QUEUE_ITEM;
NTSTATUS
@@ -104,7 +104,7 @@ IopReportTargetDeviceChangeAsyncWorker(PVOID Context)
PINTERNAL_WORK_QUEUE_ITEM Item;
Item = (PINTERNAL_WORK_QUEUE_ITEM)Context;
- PpSetCustomTargetEvent(Item->PhysicalDeviceObject, NULL, NULL, Item->Callback, Item->Context, Item->NotificationStructure);
+ PpSetCustomTargetEvent(Item->PhysicalDeviceObject, NULL, NULL, Item->Callback, Item->Context, &Item->NotificationStructure);
ObDereferenceObject(Item->PhysicalDeviceObject);
ExFreePoolWithTag(Context, ' pP');
}
@@ -502,6 +502,7 @@ IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject,
{
PINTERNAL_WORK_QUEUE_ITEM Item = NULL;
PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
+ SIZE_T WorkItemSize;
ASSERT(notifyStruct);
@@ -527,16 +528,20 @@ IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject,
return STATUS_INVALID_DEVICE_REQUEST;
}
+ /* Calculate the required size for the work item and notification structure */
+ WorkItemSize = FIELD_OFFSET(INTERNAL_WORK_QUEUE_ITEM, NotificationStructure)
+ + notifyStruct->Size;
+
/* We need to store all the data given by the caller with the WorkItem, so use our own struct */
- Item = ExAllocatePoolWithTag(NonPagedPool, sizeof(INTERNAL_WORK_QUEUE_ITEM), ' pP');
+ Item = ExAllocatePoolWithTag(NonPagedPool, WorkItemSize, ' pP');
if (!Item) return STATUS_INSUFFICIENT_RESOURCES;
/* Initialize all stuff */
ObReferenceObject(PhysicalDeviceObject);
- Item->NotificationStructure = notifyStruct;
Item->PhysicalDeviceObject = PhysicalDeviceObject;
Item->Callback = Callback;
Item->Context = Context;
+ RtlCopyMemory(&Item->NotificationStructure, notifyStruct, notifyStruct->Size);
ExInitializeWorkItem(&(Item->WorkItem), IopReportTargetDeviceChangeAsyncWorker, Item);
/* Finally, queue the item, our work here is done */