Fix hibernation crash on fresh Windows 11 25H2 (BSOD Event 41) (#1671)

* Fix hibernation crash on fresh Windows 11 25H2 (BSOD Event 41)

* follow up on the hibernation fix review: fix MDL check order and drop the risky sleep.
This commit is contained in:
audriusbuika
2026-04-15 03:22:46 +03:00
committed by GitHub
parent 5b4fae60a8
commit f63c617431
2 changed files with 36 additions and 10 deletions

View File

@@ -52,10 +52,6 @@ static uint8 BootLoaderFingerprint[WHIRLPOOL_DIGESTSIZE + SHA512_DIGESTSIZE];
static BOOL CrashDumpEnabled = FALSE;
static BOOL HibernationEnabled = FALSE;
static BOOL LegacyHibernationDriverFilterActive = FALSE;
static uint8 *HibernationWriteBuffer = NULL;
static MDL *HibernationWriteBufferMdl = NULL;
static uint32 HibernationPreventionCount = 0;
static BootEncryptionSetupRequest SetupRequest;
@@ -1208,7 +1204,21 @@ wipe:
}
// Legacy Windows XP/2003 hibernation dump filter
/*
* Legacy Windows XP/2003 hibernation dump filter.
*
* DISABLED: This code is not active - LoadImageNotifyRoutine was never
* registered via PsSetLoadImageNotifyRoutine, so none of these functions
* are reachable at runtime. Additionally the code has known issues:
* - HibernationWriteBuffer / HibernationWriteBufferMdl are never allocated
* (NULL dereference if reached)
* - MmInitializeMdl is called in a context that may run at HIGH_LEVEL
* - dataMdl->MappedSystemVa is accessed without checking MDL flags
*
* Kept behind #if 0 for historical reference. The modern hibernation
* encryption path is in DumpFilter.c (Vista+ dump filter API).
*/
#if 0
typedef NTSTATUS (*HiberDriverWriteFunctionA) (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3);
typedef NTSTATUS (*HiberDriverWriteFunctionB) (PLARGE_INTEGER writeOffset, PMDL dataMdl);
@@ -1300,7 +1310,7 @@ static NTSTATUS HiberDriverWriteFunctionFilter (int filterNumber, PLARGE_INTEGER
if (writeB)
return (*OriginalHiberDriverWriteFunctionsB[filterNumber]) (writeOffset, encryptedDataMdl);
return (*OriginalHiberDriverWriteFunctionsA[filterNumber]) (arg0WriteA, writeOffset, encryptedDataMdl, arg3WriteA);
}
@@ -1475,6 +1485,8 @@ static VOID LoadImageNotifyRoutine (PUNICODE_STRING fullImageName, HANDLE proces
KeLowerIrql (origIrql);
}
#endif /* Legacy XP/2003 hibernation filter */
static VOID SetupThreadProc (PVOID threadArg)
{

View File

@@ -266,11 +266,25 @@ static NTSTATUS DumpFilterWrite (PFILTER_EXTENSION filterExtension, PLARGE_INTEG
if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
// Require either a valid mapping or a nonpaged system VA we can read at HIGH_LEVEL.
if ((writeMdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) == 0)
TC_BUG_CHECK(STATUS_INVALID_PARAMETER);
// Resolve the system VA we can safely read at HIGH_LEVEL.
// MDL_SOURCE_IS_NONPAGED_POOL: original VA (StartVa + ByteOffset) is a kernel VA.
// MDL_MAPPED_TO_SYSTEM_VA: MappedSystemVa is the correct kernel VA (StartVa
// may point elsewhere, e.g. user-mode or stale VA).
// Windows 11 25H2+ dump stacks may provide mapped MDLs that are NOT from nonpaged
// pool, so we must prefer MappedSystemVa when available.
if (writeMdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
{
writeBuffer = writeMdl->MappedSystemVa;
}
else if (writeMdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL)
{
writeBuffer = MmGetMdlVirtualAddress (writeMdl);
}
else
{
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
}
writeBuffer = MmGetMdlVirtualAddress (writeMdl);
if (!writeBuffer)
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);