https://git.reactos.org/?p=reactos.git;a=commitdiff;h=176de8bd256c2774676b527906f8bdb1350fb34f

commit 176de8bd256c2774676b527906f8bdb1350fb34f
Author:     Timo Kreuzer <timo.kreu...@reactos.org>
AuthorDate: Wed Oct 9 13:21:29 2024 +0200
Commit:     Timo Kreuzer <timo.kreu...@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 */

Reply via email to