- Move some Mm routines from pe.c to sysldr.c where they belong.

- Create and initialize Mm Loader lock.
- Re-arrange some code in MmLoadSystemImage, no code changes yet.
- Add new LDRP_ flags for LDR_DATA_TABLE_ENTRY to the NDK.

svn path=/trunk/; revision=25881
This commit is contained in:
Alex Ionescu 2007-02-22 20:55:02 +00:00
parent 50b11bc313
commit e81f8006bb
5 changed files with 177 additions and 150 deletions

View file

@ -49,8 +49,14 @@ Author:
#define LDRP_IMAGE_NOT_AT_BASE 0x00200000
#define LDRP_COR_IMAGE 0x00400000
#define LDR_COR_OWNS_UNMAP 0x00800000
#define LDRP_DRIVER_VERIFYING 0x02000000
#define LDRP_SYSTEM_MAPPED 0x01000000
#define LDRP_IMAGE_VERIFYING 0x02000000
#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000
#define LDRP_ENTRY_NATIVE 0x08800000
#define LDRP_REDIRECTED 0x10000000
#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000
#define LDRP_MM_LOADED 0x40000000
#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000
//
// Dll Characteristics for LdrLoadDll

View file

@ -201,11 +201,71 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName,
PLOAD_IMPORTS LoadedImports = (PVOID)-2;
PCHAR MissingApiName, Buffer;
PWCHAR MissingDriverName;
PAGED_CODE();
/* Detect session-load */
if (Flags)
{
/* Sanity checks */
ASSERT(NamePrefix == NULL);
ASSERT(LoadedName == NULL);
/* Make sure the process is in session too */
if (!PsGetCurrentProcess()->ProcessInSession) return STATUS_NO_MEMORY;
}
if (ModuleObject) *ModuleObject = NULL;
if (ImageBaseAddress) *ImageBaseAddress = NULL;
DPRINT("Loading Module %wZ...\n", FileName);
/* Allocate a buffer we'll use for names */
Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
if (!Buffer)
{
/* Fail */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Check for a separator */
if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
{
PWCHAR p;
ULONG BaseLength;
/* Loop the path until we get to the base name */
p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
/* Get the length */
BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
BaseLength *= sizeof(WCHAR);
/* Setup the string */
BaseName.Length = (USHORT)BaseLength;
BaseName.Buffer = p;
}
else
{
/* Otherwise, we already have a base name */
BaseName.Length = FileName->Length;
BaseName.Buffer = FileName->Buffer;
}
/* Setup the maximum length */
BaseName.MaximumLength = BaseName.Length;
/* Now compute the base directory */
BaseDirectory = *FileName;
BaseDirectory.Length -= BaseName.Length;
BaseDirectory.MaximumLength = BaseDirectory.Length;
/* And the prefix, which for now is just the name itself */
PrefixName = *FileName;
/* Check if we have a prefix */
if (NamePrefix) DPRINT1("Prefixed images are not yet supported!\n");
/* Check if we already have a name, use it instead */
if (LoadedName) BaseName = *LoadedName;
/* Open the Module */
InitializeObjectAttributes(&ObjectAttributes,
@ -370,50 +430,6 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName,
return Status;
}
/* Allocate a buffer we'll use for names */
Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
if (!Buffer)
{
/* Fail */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Check for a separator */
if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
{
PWCHAR p;
ULONG BaseLength;
/* Loop the path until we get to the base name */
p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
/* Get the length */
BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
BaseLength *= sizeof(WCHAR);
/* Setup the string */
BaseName.Length = (USHORT)BaseLength;
BaseName.Buffer = p;
}
else
{
/* Otherwise, we already have a base name */
BaseName.Length = FileName->Length;
BaseName.Buffer = FileName->Buffer;
}
/* Setup the maximum length */
BaseName.MaximumLength = BaseName.Length;
/* Now compute the base directory */
BaseDirectory = *FileName;
BaseDirectory.Length -= BaseName.Length;
BaseDirectory.MaximumLength = BaseDirectory.Length;
/* And the prefix */
PrefixName = *FileName;
/* Calculate the size we'll need for the entry and allocate it */
EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
BaseName.Length +

View file

@ -453,6 +453,7 @@ MmInit1(ULONG_PTR FirstKrnlPhysAddr,
}
BOOLEAN RmapReady, PageOpReady, SectionsReady, PagingReady;
extern KMUTANT MmSystemLoadLock;
BOOLEAN
NTAPI
@ -461,6 +462,9 @@ MmInitSystem(IN ULONG Phase,
{
if (Phase == 0)
{
/* Initialize the Loader Lock */
KeInitializeMutant(&MmSystemLoadLock, FALSE);
/* Reload boot drivers */
MiReloadBootLoadedDrivers(LoaderBlock);

View file

@ -677,108 +677,4 @@ 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

@ -17,6 +17,7 @@
LIST_ENTRY PsLoadedModuleList;
KSPIN_LOCK PsLoadedModuleSpinLock;
PVOID PsNtosImageBase;
KMUTANT MmSystemLoadLock;
/* FUNCTIONS *****************************************************************/
@ -914,3 +915,107 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
/* We're done */
return TRUE;
}
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;
}