https://git.reactos.org/?p=reactos.git;a=commitdiff;h=58ad5d9e02bbb08c3229ee06ed25f64e13c2a2f0

commit 58ad5d9e02bbb08c3229ee06ed25f64e13c2a2f0
Author:     Jérôme Gardou <jerome.gar...@reactos.org>
AuthorDate: Wed Dec 9 12:24:23 2020 +0100
Commit:     Jérôme Gardou <jerome.gar...@reactos.org>
CommitDate: Wed Dec 9 12:24:23 2020 +0100

    [SCSIPORT] Fix locking the device extension.
    
    From MSDN:
    It is an error to call KeReleaseSpinLockFromDpcLevel if the specified spin 
lock was acquired by calling KeAcquireSpinLock because the caller's original 
IRQL is not restored, which can cause deadlocks or fatal page faults.
---
 drivers/storage/port/scsiport/fdo.c      |  8 ++------
 drivers/storage/port/scsiport/scsi.c     | 32 ++++++++++++++++++--------------
 drivers/storage/port/scsiport/scsiport.h |  3 ++-
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/storage/port/scsiport/fdo.c 
b/drivers/storage/port/scsiport/fdo.c
index 2cc89ea7353..052d5f62fa5 100644
--- a/drivers/storage/port/scsiport/fdo.c
+++ b/drivers/storage/port/scsiport/fdo.c
@@ -150,12 +150,8 @@ FdoSendInquiry(
             /* Acquire the spinlock */
             KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
 
-            /* Process the request */
-            SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
-
-            /* SpiGetNextRequestFromLun() releases the spinlock,
-                so we just lower irql back to what it was before */
-            KeLowerIrql(Irql);
+            /* Process the request. SpiGetNextRequestFromLun will unlock for 
us */
+            SpiGetNextRequestFromLun(DeviceExtension, LunExtension, &Irql);
         }
 
         /* Check if data overrun happened */
diff --git a/drivers/storage/port/scsiport/scsi.c 
b/drivers/storage/port/scsiport/scsi.c
index 6cfd1ba29f3..0aa7d36a3d5 100644
--- a/drivers/storage/port/scsiport/scsi.c
+++ b/drivers/storage/port/scsiport/scsi.c
@@ -258,11 +258,8 @@ ScsiPortDispatchScsi(
 
             if (lunExt->SrbInfo.Srb == NULL)
             {
-                /* Get next logical unit request */
-                SpiGetNextRequestFromLun(portExt, lunExt);
-
-                /* SpiGetNextRequestFromLun() releases the spinlock */
-                KeLowerIrql(Irql);
+                /* Get next logical unit request. SpiGetNextRequestFromLun 
releases the lock. */
+                SpiGetNextRequestFromLun(portExt, lunExt, &Irql);
             }
             else
             {
@@ -344,7 +341,9 @@ ScsiPortDispatchScsi(
 VOID
 SpiGetNextRequestFromLun(
     _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
-    _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension)
+    _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
+    _Inout_opt_ PKIRQL OldIrql
+)
 {
     PIO_STACK_LOCATION IrpStack;
     PIRP NextIrp;
@@ -357,7 +356,10 @@ SpiGetNextRequestFromLun(
         !(LunExtension->Flags & SCSI_PORT_LU_ACTIVE))
     {
         /* Release the spinlock and exit */
-        KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+        if (OldIrql != NULL)
+            KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
+        else
+            KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
         return;
     }
 
@@ -385,7 +387,10 @@ SpiGetNextRequestFromLun(
             LunExtension->AttemptCount = 0;
 
             /* Release the spinlock */
-            KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+            if (OldIrql != NULL)
+                KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
+            else
+                KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
 
             /* Start the next pending request */
             IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, 
(PULONG)NULL, NULL);
@@ -495,8 +500,7 @@ SpiSenseCompletionRoutine(
         lunExt->Flags &= ~LUNEX_NEED_REQUEST_SENSE;
 
         // SpiGetNextRequestFromLun releases the lock
-        SpiGetNextRequestFromLun(portExt, lunExt);
-        KeLowerIrql(irql);
+        SpiGetNextRequestFromLun(portExt, lunExt, &irql);
 
         InitialSrb->SrbStatus &= ~SRB_STATUS_QUEUE_FROZEN;
     }
@@ -774,8 +778,8 @@ SpiProcessCompletedRequest(
         if (!(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) &&
             LunExtension->RequestTimeout == -1)
         {
-            /* Start the next packet */
-            SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
+            /* Start the next packet. SpiGetNextRequestFromLun will release 
the lock for us */
+            SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
         }
         else
         {
@@ -891,7 +895,7 @@ Error:
         && (Srb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE))
     {
         if (LunExtension->RequestTimeout == -1)
-            SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
+            SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
         else
             KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
     }
@@ -1342,7 +1346,7 @@ TryAgain:
             LunExtension->ReadyLun = NULL;
 
             /* Get next request for this LUN */
-            SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
+            SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
 
             /* Still ready requests exist?
                If yes - get spinlock, if no - stop here */
diff --git a/drivers/storage/port/scsiport/scsiport.h 
b/drivers/storage/port/scsiport/scsiport.h
index a81ef4cbb41..d3ee010cab1 100644
--- a/drivers/storage/port/scsiport/scsiport.h
+++ b/drivers/storage/port/scsiport/scsiport.h
@@ -437,7 +437,8 @@ RegistryInitLunKey(
 VOID
 SpiGetNextRequestFromLun(
     _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
-    _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension);
+    _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
+    _Inout_opt_ PKIRQL OldIrql);
 
 IO_DPC_ROUTINE ScsiPortDpcForIsr;
 DRIVER_DISPATCH ScsiPortDispatchScsi;

Reply via email to