- Stub LdrVerifyMappedImageMatchesChecksum.

- Separate locating the system DLL from initializing it.
- Implement split-phase PsInitSystem for Phase 0 and 1, and make system dll initialization as part of phase 1.
- Add MmVerifyImageIsOkForMpUse and MmCheckSystemImage to validate the system DLL.
- Add a separate bugcheck for each failure in PsLocateSystemDll, matching with the NT bugchecks that would occur.

svn path=/trunk/; revision=24437
This commit is contained in:
Alex Ionescu 2006-10-08 02:10:34 +00:00
parent ebd9a573ec
commit 9088db842e
6 changed files with 213 additions and 16 deletions

View file

@ -99,4 +99,12 @@ LdrUnlockLoaderLock(
IN ULONG Cookie OPTIONAL
);
BOOLEAN
NTAPI
LdrVerifyMappedImageMatchesChecksum(
IN PVOID BaseAddress,
IN ULONG NumberOfBytes,
IN ULONG FileLength
);
#endif

View file

@ -18,6 +18,16 @@
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
LdrVerifyMappedImageMatchesChecksum(IN PVOID BaseAddress,
IN ULONG NumberOfBytes,
IN ULONG FileLength)
{
/* FIXME: TODO */
return TRUE;
}
/*
* @implemented
*/

View file

@ -953,9 +953,11 @@ ExPhase2Init(PVOID Context)
/* Initialize shared user page. Set dos system path, dos device map, etc. */
InitSystemSharedUserPage(KeLoaderBlock);
/* Initailize the Process Manager at Phase 1 */
if (!PsInitSystem()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
/* Launch initial process */
Status = ExpLoadInitialProcess(&ProcessHandle,
&ThreadHandle);
Status = ExpLoadInitialProcess(&ProcessHandle, &ThreadHandle);
/* Wait 5 seconds for it to initialize */
Timeout.QuadPart = Int32x32To64(5, -10000000);

View file

@ -335,6 +335,13 @@ typedef VOID
/* FUNCTIONS */
NTSTATUS
NTAPI
MmCheckSystemImage(
IN HANDLE ImageHandle,
IN BOOLEAN PurgeSection
);
/* aspace.c ******************************************************************/
VOID

View file

@ -677,4 +677,108 @@ l_Return:
return nStatus;
}
BOOLEAN
NTAPI
MmVerifyImageIsOkForMpUse(IN PVOID BaseAddress)
{
PIMAGE_NT_HEADERS NtHeader;
PAGED_CODE();
/* Get NT Headers */
NtHeader = RtlImageNtHeader(BaseAddress);
if (NtHeader)
{
/* Check if this image is only safe for UP while we have 2+ CPUs */
if ((KeNumberProcessors > 1) &&
(NtHeader->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY))
{
/* Fail */
return FALSE;
}
}
/* Otherwise, it's safe */
return TRUE;
}
NTSTATUS
NTAPI
MmCheckSystemImage(IN HANDLE ImageHandle,
IN BOOLEAN PurgeSection)
{
NTSTATUS Status;
HANDLE SectionHandle;
PVOID ViewBase = NULL;
SIZE_T ViewSize = 0;
IO_STATUS_BLOCK IoStatusBlock;
FILE_STANDARD_INFORMATION FileStandardInfo;
KAPC_STATE ApcState;
PAGED_CODE();
/* Create a section for the DLL */
Status = ZwCreateSection(&SectionHandle,
SECTION_MAP_EXECUTE,
NULL,
NULL,
PAGE_EXECUTE,
SEC_COMMIT,
ImageHandle);
if (!NT_SUCCESS(Status)) return Status;
/* Make sure we're in the system process */
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
/* Map it */
Status = ZwMapViewOfSection(SectionHandle,
NtCurrentProcess(),
&ViewBase,
0,
0,
NULL,
&ViewSize,
ViewShare,
0,
PAGE_EXECUTE);
if (!NT_SUCCESS(Status))
{
/* We failed, close the handle and return */
KeUnstackDetachProcess(&ApcState);
ZwClose(SectionHandle);
return Status;
}
/* Now query image information */
Status = ZwQueryInformationFile(ImageHandle,
&IoStatusBlock,
&FileStandardInfo,
sizeof(FileStandardInfo),
FileStandardInformation);
if ( NT_SUCCESS(Status) )
{
/* First, verify the checksum */
if (!LdrVerifyMappedImageMatchesChecksum(ViewBase,
FileStandardInfo.
EndOfFile.LowPart,
FileStandardInfo.
EndOfFile.LowPart))
{
/* Set checksum failure */
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
}
/* Check that it's a valid SMP image if we have more then one CPU */
if (!MmVerifyImageIsOkForMpUse(ViewBase))
{
/* Otherwise it's not the right image */
Status = STATUS_IMAGE_MP_UP_MISMATCH;
}
}
/* Unmap the section, close the handle, and return status */
ZwUnmapViewOfSection(NtCurrentProcess(), ViewBase);
KeUnstackDetachProcess(&ApcState);
ZwClose(SectionHandle);
return Status;
}
/* EOF */

View file

@ -12,6 +12,8 @@
#define NDEBUG
#include <internal/debug.h>
extern ULONG ExpInitializationPhase;
GENERIC_MAPPING PspProcessMapping =
{
STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
@ -77,11 +79,6 @@ PspLookupKernelUserEntryPoints(VOID)
{
NTSTATUS Status;
/* Get user-mode startup thunk */
Status = PspLookupSystemDllEntryPoint(&ThunkName,
&PspSystemDllEntryPoint);
if (!NT_SUCCESS(Status)) return Status;
/* Get user-mode APC trampoline */
Status = PspLookupSystemDllEntryPoint(&ApcName,
&KeUserApcDispatcher);
@ -178,10 +175,14 @@ PsLocateSystemDll(VOID)
&IoStatusBlock,
FILE_SHARE_READ,
0);
if (!NT_SUCCESS(Status)) return Status;
if (!NT_SUCCESS(Status))
{
/* Failed, bugcheck */
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 2, 0, 0);
}
/* FIXME: Check if the image is valid */
Status = STATUS_SUCCESS; //MmCheckSystemImage(FileHandle, TRUE);
Status = MmCheckSystemImage(FileHandle, TRUE);
if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
{
/* Raise a hard error */
@ -204,7 +205,11 @@ PsLocateSystemDll(VOID)
SEC_IMAGE,
FileHandle);
ZwClose(FileHandle);
if (!NT_SUCCESS(Status)) return Status;
if (!NT_SUCCESS(Status))
{
/* Failed, bugcheck */
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 3, 0, 0);
}
/* Reference the Section */
Status = ObReferenceObjectByHandle(SectionHandle,
@ -214,14 +219,58 @@ PsLocateSystemDll(VOID)
(PVOID*)&PspSystemDllSection,
NULL);
ZwClose(SectionHandle);
if (!NT_SUCCESS(Status)) return Status;
if (!NT_SUCCESS(Status))
{
/* Failed, bugcheck */
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 4, 0, 0);
}
/* Map it */
Status = PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase);
if (!NT_SUCCESS(Status))
{
/* Failed, bugcheck */
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 5, 0, 0);
}
/* Now get the Entrypoints */
PspLookupKernelUserEntryPoints();
return STATUS_SUCCESS;
/* Return status */
return Status;
}
NTSTATUS
NTAPI
PspInitializeSystemDll(VOID)
{
NTSTATUS Status;
/* Get user-mode startup thunk */
Status = PspLookupSystemDllEntryPoint(&ThunkName, &PspSystemDllEntryPoint);
if (!NT_SUCCESS(Status))
{
/* Failed, bugcheck */
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 7, 0, 0);
}
/* Get all the other entrypoints */
Status = PspLookupKernelUserEntryPoints();
if (!NT_SUCCESS(Status))
{
/* Failed, bugcheck */
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 8, 0, 0);
}
/* Return status */
return Status;
}
BOOLEAN
NTAPI
PspInitPhase1(VOID)
{
/* Initialize the System DLL and return status of operation */
if (!NT_SUCCESS(PspInitializeSystemDll())) return FALSE;
return TRUE;
}
BOOLEAN
@ -428,8 +477,25 @@ BOOLEAN
NTAPI
PsInitSystem(VOID)
{
/* For now, do only Phase 0 */
return PspInitPhase0();
/* Check the initialization phase */
switch (ExpInitializationPhase)
{
case 0:
/* Do Phase 0 */
return PspInitPhase0();
case 1:
/* Do Phase 1 */
return PspInitPhase1();
default:
/* Don't know any other phase! Bugcheck! */
KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
return FALSE;
}
}
/* PUBLIC FUNCTIONS **********************************************************/