[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.
This commit is contained in:
Jérôme Gardou 2020-12-09 12:24:23 +01:00
parent 484e959c29
commit 58ad5d9e02
3 changed files with 22 additions and 21 deletions

View file

@ -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 */

View file

@ -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 */

View file

@ -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;