diff --git a/reactos/include/ndk/ldrfuncs.h b/reactos/include/ndk/ldrfuncs.h index 179bbfe00e8..abb69242345 100644 --- a/reactos/include/ndk/ldrfuncs.h +++ b/reactos/include/ndk/ldrfuncs.h @@ -99,4 +99,12 @@ LdrUnlockLoaderLock( IN ULONG Cookie OPTIONAL ); +BOOLEAN +NTAPI +LdrVerifyMappedImageMatchesChecksum( + IN PVOID BaseAddress, + IN ULONG NumberOfBytes, + IN ULONG FileLength +); + #endif diff --git a/reactos/lib/rtl/image.c b/reactos/lib/rtl/image.c index e7dafc25e25..1df8af534c1 100644 --- a/reactos/lib/rtl/image.c +++ b/reactos/lib/rtl/image.c @@ -18,6 +18,16 @@ /* FUNCTIONS *****************************************************************/ +BOOLEAN +NTAPI +LdrVerifyMappedImageMatchesChecksum(IN PVOID BaseAddress, + IN ULONG NumberOfBytes, + IN ULONG FileLength) +{ + /* FIXME: TODO */ + return TRUE; +} + /* * @implemented */ diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index 4c32cd3c5f9..66ca9d6eea2 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -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); diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 21d5fee28ca..b9919fe30d2 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -335,6 +335,13 @@ typedef VOID /* FUNCTIONS */ +NTSTATUS +NTAPI +MmCheckSystemImage( + IN HANDLE ImageHandle, + IN BOOLEAN PurgeSection +); + /* aspace.c ******************************************************************/ VOID diff --git a/reactos/ntoskrnl/mm/pe.c b/reactos/ntoskrnl/mm/pe.c index 41502117a5c..3055e9cf33a 100644 --- a/reactos/ntoskrnl/mm/pe.c +++ b/reactos/ntoskrnl/mm/pe.c @@ -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 */ diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index d42fad424c2..6f699d1cccb 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -12,6 +12,8 @@ #define NDEBUG #include +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 **********************************************************/