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;