[NTOS:EX] Check whether the boot-time drivers are safe to use on MP systems (#7744)

Invoke the MmVerifyImageIsOkForMpUse() helper. If the boot-time driver
only supports a uniprocessor system, bugcheck with UP_DRIVER_ON_MP_SYSTEM.

https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x92--up-driver-on-mp-system

Note that we don't do this check very soon at boot time (e.g. in
MiReloadBootLoadedDrivers or MiInitializeLoadedModuleList), but only
after loading the drivers' debug symbols (if any).
The reason is simply to ease debugging in case we bugcheck: this allows
having the debugger set up with the symbols for this driver.

For automatic and manual driver loading, MmVerifyImageIsOkForMpUse()
is invoked by MmCheckSystemImage() but in this case, there is graceful
failure and no bugcheck.
This commit is contained in:
Hermès Bélusca-Maïto 2025-03-03 22:09:12 +01:00
parent 4750cbe55b
commit 125f94d8ab
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 23 additions and 6 deletions

View file

@ -863,6 +863,16 @@ ExpLoadBootSymbols(
LdrEntry->DllBase,
(ULONG_PTR)PsGetCurrentProcessId());
}
#ifdef CONFIG_SMP
/* Check that the image is safe to use if we have more than one CPU */
if (!MmVerifyImageIsOkForMpUse(LdrEntry->DllBase))
{
KeBugCheckEx(UP_DRIVER_ON_MP_SYSTEM,
(ULONG_PTR)LdrEntry->DllBase,
0, 0, 0);
}
#endif // CONFIG_SMP
}
}

View file

@ -1649,6 +1649,13 @@ MmUnloadSystemImage(
IN PVOID ImageHandle
);
#ifdef CONFIG_SMP
BOOLEAN
NTAPI
MmVerifyImageIsOkForMpUse(
_In_ PVOID BaseAddress);
#endif // CONFIG_SMP
NTSTATUS
NTAPI
MmCheckSystemImage(

View file

@ -2716,12 +2716,13 @@ MiEnablePagingOfDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
if (PointerPte) MiSetPagingOfDriver(PointerPte, LastPte);
}
#ifdef CONFIG_SMP
FORCEINLINE
BOOLEAN
MiVerifyImageIsOkForMpUse(
_In_ PIMAGE_NT_HEADERS NtHeaders)
{
/* Fail if we have 2+ CPUs, but the image is only safe for UP */
/* Fail if we have more than one CPU, but the image is only safe for UP */
if ((KeNumberProcessors > 1) &&
(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY))
{
@ -2731,8 +2732,6 @@ MiVerifyImageIsOkForMpUse(
return TRUE;
}
// TODO: Use this function to verify that the loaded boot drivers
// (in ExpLoadBootSymbols) are compatible with MP.
BOOLEAN
NTAPI
MmVerifyImageIsOkForMpUse(
@ -2741,13 +2740,14 @@ MmVerifyImageIsOkForMpUse(
PIMAGE_NT_HEADERS NtHeaders;
PAGED_CODE();
/* Get the NT headers. If none, suppose the image
* is safe to use, otherwise invoke the helper. */
/* Get the NT headers. If none, suppose the image is safe
* to use on an MP system, otherwise invoke the helper. */
NtHeaders = RtlImageNtHeader(BaseAddress);
if (!NtHeaders)
return TRUE;
return MiVerifyImageIsOkForMpUse(NtHeaders);
}
#endif // CONFIG_SMP
NTSTATUS
NTAPI
@ -2847,7 +2847,7 @@ MmCheckSystemImage(
}
#ifdef CONFIG_SMP
/* Check that it's a valid SMP image if we have more than one CPU */
/* Check that the image is safe to use if we have more than one CPU */
if (!MiVerifyImageIsOkForMpUse(NtHeaders))
{
/* Otherwise it's not the right image */