[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 */ /* Acquire the spinlock */
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql); KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
/* Process the request */ /* Process the request. SpiGetNextRequestFromLun will unlock for us */
SpiGetNextRequestFromLun(DeviceExtension, LunExtension); SpiGetNextRequestFromLun(DeviceExtension, LunExtension, &Irql);
/* SpiGetNextRequestFromLun() releases the spinlock,
so we just lower irql back to what it was before */
KeLowerIrql(Irql);
} }
/* Check if data overrun happened */ /* Check if data overrun happened */

View file

@ -258,11 +258,8 @@ ScsiPortDispatchScsi(
if (lunExt->SrbInfo.Srb == NULL) if (lunExt->SrbInfo.Srb == NULL)
{ {
/* Get next logical unit request */ /* Get next logical unit request. SpiGetNextRequestFromLun releases the lock. */
SpiGetNextRequestFromLun(portExt, lunExt); SpiGetNextRequestFromLun(portExt, lunExt, &Irql);
/* SpiGetNextRequestFromLun() releases the spinlock */
KeLowerIrql(Irql);
} }
else else
{ {
@ -344,7 +341,9 @@ ScsiPortDispatchScsi(
VOID VOID
SpiGetNextRequestFromLun( SpiGetNextRequestFromLun(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _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; PIO_STACK_LOCATION IrpStack;
PIRP NextIrp; PIRP NextIrp;
@ -357,7 +356,10 @@ SpiGetNextRequestFromLun(
!(LunExtension->Flags & SCSI_PORT_LU_ACTIVE)) !(LunExtension->Flags & SCSI_PORT_LU_ACTIVE))
{ {
/* Release the spinlock and exit */ /* Release the spinlock and exit */
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); if (OldIrql != NULL)
KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
else
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
return; return;
} }
@ -385,7 +387,10 @@ SpiGetNextRequestFromLun(
LunExtension->AttemptCount = 0; LunExtension->AttemptCount = 0;
/* Release the spinlock */ /* Release the spinlock */
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); if (OldIrql != NULL)
KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql);
else
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
/* Start the next pending request */ /* Start the next pending request */
IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL); IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL);
@ -495,8 +500,7 @@ SpiSenseCompletionRoutine(
lunExt->Flags &= ~LUNEX_NEED_REQUEST_SENSE; lunExt->Flags &= ~LUNEX_NEED_REQUEST_SENSE;
// SpiGetNextRequestFromLun releases the lock // SpiGetNextRequestFromLun releases the lock
SpiGetNextRequestFromLun(portExt, lunExt); SpiGetNextRequestFromLun(portExt, lunExt, &irql);
KeLowerIrql(irql);
InitialSrb->SrbStatus &= ~SRB_STATUS_QUEUE_FROZEN; InitialSrb->SrbStatus &= ~SRB_STATUS_QUEUE_FROZEN;
} }
@ -774,8 +778,8 @@ SpiProcessCompletedRequest(
if (!(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) && if (!(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) &&
LunExtension->RequestTimeout == -1) LunExtension->RequestTimeout == -1)
{ {
/* Start the next packet */ /* Start the next packet. SpiGetNextRequestFromLun will release the lock for us */
SpiGetNextRequestFromLun(DeviceExtension, LunExtension); SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
} }
else else
{ {
@ -891,7 +895,7 @@ Error:
&& (Srb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE)) && (Srb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE))
{ {
if (LunExtension->RequestTimeout == -1) if (LunExtension->RequestTimeout == -1)
SpiGetNextRequestFromLun(DeviceExtension, LunExtension); SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
else else
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
} }
@ -1342,7 +1346,7 @@ TryAgain:
LunExtension->ReadyLun = NULL; LunExtension->ReadyLun = NULL;
/* Get next request for this LUN */ /* Get next request for this LUN */
SpiGetNextRequestFromLun(DeviceExtension, LunExtension); SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL);
/* Still ready requests exist? /* Still ready requests exist?
If yes - get spinlock, if no - stop here */ If yes - get spinlock, if no - stop here */

View file

@ -437,7 +437,8 @@ RegistryInitLunKey(
VOID VOID
SpiGetNextRequestFromLun( SpiGetNextRequestFromLun(
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _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; IO_DPC_ROUTINE ScsiPortDpcForIsr;
DRIVER_DISPATCH ScsiPortDispatchScsi; DRIVER_DISPATCH ScsiPortDispatchScsi;