secured buffer access in NtCreateSection(), NtOpenSection(), NtMapViewOfSection(), NtQuerySection() and NtExtendSection() Modified: trunk/reactos/include/ntos/zw.h Modified: trunk/reactos/ntoskrnl/mm/section.c _____
Modified: trunk/reactos/include/ntos/zw.h --- trunk/reactos/include/ntos/zw.h 2005-02-15 14:37:53 UTC (rev 13582) +++ trunk/reactos/include/ntos/zw.h 2005-02-15 15:46:22 UTC (rev 13583) @@ -5420,10 +5420,10 @@
STDCALL NtQuerySection( IN HANDLE SectionHandle, - IN CINT SectionInformationClass, + IN SECTION_INFORMATION_CLASS SectionInformationClass, OUT PVOID SectionInformation, - IN ULONG Length, - OUT PULONG ResultLength + IN ULONG SectionInformationLength, + OUT PULONG ResultLength OPTIONAL );
/* @@ -6451,10 +6451,10 @@ STDCALL ZwQuerySection( IN HANDLE SectionHandle, - IN CINT SectionInformationClass, + IN SECTION_INFORMATION_CLASS SectionInformationClass, OUT PVOID SectionInformation, - IN ULONG Length, - OUT PULONG ResultLength + IN ULONG SectionInformationLength, + OUT PULONG ResultLength OPTIONAL );
typedef struct _SECTION_IMAGE_INFORMATION _____
Modified: trunk/reactos/ntoskrnl/mm/section.c --- trunk/reactos/ntoskrnl/mm/section.c 2005-02-15 14:37:53 UTC (rev 13582) +++ trunk/reactos/ntoskrnl/mm/section.c 2005-02-15 15:46:22 UTC (rev 13583) @@ -50,6 +50,12 @@
#define SWAPENTRY_FROM_SSE(E) ((E) >> 1) #define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1)
+static const INFORMATION_CLASS_INFO ExSectionInfoClass[] = +{ + ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */ + ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */ +}; + /* FUNCTIONS *****************************************************************/
/* Note: Mmsp prefix denotes "Memory Manager Section Private". */ @@ -3309,9 +3315,36 @@ IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL) { + LARGE_INTEGER SafeMaximumSize; PSECTION_OBJECT SectionObject; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS;
+ PreviousMode = ExGetPreviousMode(); + + if(MaximumSize != NULL && PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(MaximumSize, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + /* make a copy on the stack */ + SafeMaximumSize = *MaximumSize; + MaximumSize = &SafeMaximumSize; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + /* * Check the protection */ @@ -3367,18 +3400,53 @@ ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) { - NTSTATUS Status; + HANDLE hSection; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(SectionHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + }
- *SectionHandle = 0; - Status = ObOpenObjectByName(ObjectAttributes, MmSectionObjectType, NULL, - UserMode, + PreviousMode, DesiredAccess, NULL, - SectionHandle); + &hSection);
+ if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *SectionHandle = hSection; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + return(Status); }
@@ -3487,26 +3555,77 @@ * @implemented */ NTSTATUS STDCALL -NtMapViewOfSection(HANDLE SectionHandle, - HANDLE ProcessHandle, - PVOID* BaseAddress, - ULONG ZeroBits, - ULONG CommitSize, - PLARGE_INTEGER SectionOffset, - PULONG ViewSize, - SECTION_INHERIT InheritDisposition, - ULONG AllocationType, - ULONG Protect) +NtMapViewOfSection(IN HANDLE SectionHandle, + IN HANDLE ProcessHandle, + IN OUT PVOID* BaseAddress OPTIONAL, + IN ULONG ZeroBits OPTIONAL, + IN ULONG CommitSize, + IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, + IN OUT PULONG ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType OPTIONAL, + IN ULONG Protect) { + PVOID SafeBaseAddress; + LARGE_INTEGER SafeSectionOffset; + ULONG SafeViewSize; PSECTION_OBJECT Section; PEPROCESS Process; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; PMADDRESS_SPACE AddressSpace; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + SafeBaseAddress = NULL; + SafeSectionOffset.QuadPart = 0; + SafeViewSize = 0; + + _SEH_TRY + { + if(BaseAddress != NULL) + { + ProbeForWrite(BaseAddress, + sizeof(PVOID), + sizeof(ULONG)); + SafeBaseAddress = *BaseAddress; + } + if(SectionOffset != NULL) + { + ProbeForWrite(SectionOffset, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + SafeSectionOffset = *SectionOffset; + } + ProbeForWrite(ViewSize, + sizeof(ULONG), + sizeof(ULONG)); + SafeViewSize = *ViewSize; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + SafeBaseAddress = (BaseAddress != NULL ? *BaseAddress : NULL); + SafeSectionOffset.QuadPart = (SectionOffset != NULL ? SectionOffset->QuadPart : 0); + SafeViewSize = (ViewSize != NULL ? *ViewSize : 0); + }
Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_VM_OPERATION, PsProcessType, - UserMode, + PreviousMode, (PVOID*)(PVOID)&Process, NULL); if (!NT_SUCCESS(Status)) @@ -3519,7 +3638,7 @@ Status = ObReferenceObjectByHandle(SectionHandle, SECTION_MAP_READ, MmSectionObjectType, - UserMode, + PreviousMode, (PVOID*)(PVOID)&Section, NULL); if (!(NT_SUCCESS(Status))) @@ -3531,17 +3650,42 @@
Status = MmMapViewOfSection(Section, Process, - BaseAddress, + (BaseAddress != NULL ? &SafeBaseAddress : NULL), ZeroBits, CommitSize, - SectionOffset, - ViewSize, + (SectionOffset != NULL ? &SafeSectionOffset : NULL), + (ViewSize != NULL ? &SafeViewSize : NULL), InheritDisposition, AllocationType, Protect);
ObDereferenceObject(Section); ObDereferenceObject(Process); + + if(NT_SUCCESS(Status)) + { + /* copy parameters back to the caller */ + _SEH_TRY + { + if(BaseAddress != NULL) + { + *BaseAddress = SafeBaseAddress; + } + if(SectionOffset != NULL) + { + *SectionOffset = SafeSectionOffset; + } + if(ViewSize != NULL) + { + *ViewSize = SafeViewSize; + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + }
return(Status); } @@ -3809,16 +3953,19 @@ PVOID BaseAddress) { PEPROCESS Process; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status;
DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n", ProcessHandle, BaseAddress);
+ PreviousMode = ExGetPreviousMode(); + DPRINT("Referencing process\n"); Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_VM_OPERATION, PsProcessType, - UserMode, + PreviousMode, (PVOID*)(PVOID)&Process, NULL); if (!NT_SUCCESS(Status)) @@ -3857,98 +4004,120 @@ * * @return Status. * - * @todo Guard by SEH. * @implemented */ NTSTATUS STDCALL NtQuerySection(IN HANDLE SectionHandle, - IN CINT SectionInformationClass, + IN SECTION_INFORMATION_CLASS SectionInformationClass, OUT PVOID SectionInformation, - IN ULONG Length, - OUT PULONG ResultLength) + IN ULONG SectionInformationLength, + OUT PULONG ResultLength OPTIONAL) { PSECTION_OBJECT Section; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DefaultQueryInfoBufferCheck(SectionInformationClass, + ExSectionInfoClass, + SectionInformation, + SectionInformationLength, + ResultLength, + PreviousMode, + &Status);
+ if(!NT_SUCCESS(Status)) + { + DPRINT1("NtQuerySection() failed, Status: 0x%x\n", Status); + return Status; + } + Status = ObReferenceObjectByHandle(SectionHandle, SECTION_QUERY, MmSectionObjectType, - UserMode, + PreviousMode, (PVOID*)(PVOID)&Section, NULL); - if (!(NT_SUCCESS(Status))) + if (NT_SUCCESS(Status)) { - return(Status); - } - - switch (SectionInformationClass) - { - case SectionBasicInformation: + switch (SectionInformationClass) + { + case SectionBasicInformation: { - PSECTION_BASIC_INFORMATION Sbi; + PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
- if (Length != sizeof(SECTION_BASIC_INFORMATION)) + _SEH_TRY { - ObDereferenceObject(Section); - return(STATUS_INFO_LENGTH_MISMATCH); - } + Sbi->Attributes = Section->AllocationAttributes; + if (Section->AllocationAttributes & SEC_IMAGE) + { + Sbi->BaseAddress = 0; + Sbi->Size.QuadPart = 0; + } + else + { + Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress; + Sbi->Size.QuadPart = Section->Segment->Length; + }
- Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation; - - Sbi->Attributes = Section->AllocationAttributes; - if (Section->AllocationAttributes & SEC_IMAGE) - { - Sbi->BaseAddress = 0; - Sbi->Size.QuadPart = 0; + if (ResultLength != NULL) + { + *ResultLength = sizeof(SECTION_BASIC_INFORMATION); + } + Status = STATUS_SUCCESS; } - else + _SEH_HANDLE { - Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress; - Sbi->Size.QuadPart = Section->Segment->Length; + Status = _SEH_GetExceptionCode(); } - - *ResultLength = sizeof(SECTION_BASIC_INFORMATION); - Status = STATUS_SUCCESS; + _SEH_END; + break; }
- case SectionImageInformation: + case SectionImageInformation: { - PSECTION_IMAGE_INFORMATION Sii; + PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
- if (Length != sizeof(SECTION_IMAGE_INFORMATION)) + _SEH_TRY { - ObDereferenceObject(Section); - return(STATUS_INFO_LENGTH_MISMATCH); + memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION)); + if (Section->AllocationAttributes & SEC_IMAGE) + { + PMM_IMAGE_SECTION_OBJECT ImageSectionObject; + ImageSectionObject = Section->ImageSection; + + Sii->EntryPoint = ImageSectionObject->EntryPoint; + Sii->StackReserve = ImageSectionObject->StackReserve; + Sii->StackCommit = ImageSectionObject->StackCommit; + Sii->Subsystem = ImageSectionObject->Subsystem; + Sii->MinorSubsystemVersion = ImageSectionObject->MinorSubsystemVersion; + Sii->MajorSubsystemVersion = ImageSectionObject->MajorSubsystemVersion; + Sii->Characteristics = ImageSectionObject->ImageCharacteristics; + Sii->ImageNumber = ImageSectionObject->Machine; + Sii->Executable = ImageSectionObject->Executable; + } + + if (ResultLength != NULL) + { + *ResultLength = sizeof(SECTION_IMAGE_INFORMATION); + } + Status = STATUS_SUCCESS; } - - Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation; - memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION)); - if (Section->AllocationAttributes & SEC_IMAGE) + _SEH_HANDLE { - PMM_IMAGE_SECTION_OBJECT ImageSectionObject; - ImageSectionObject = Section->ImageSection; - - Sii->EntryPoint = ImageSectionObject->EntryPoint; - Sii->StackReserve = ImageSectionObject->StackReserve; - Sii->StackCommit = ImageSectionObject->StackCommit; - Sii->Subsystem = ImageSectionObject->Subsystem; - Sii->MinorSubsystemVersion = ImageSectionObject->MinorSubsystemVersion; - Sii->MajorSubsystemVersion = ImageSectionObject->MajorSubsystemVersion; - Sii->Characteristics = ImageSectionObject->ImageCharacteristics; - Sii->ImageNumber = ImageSectionObject->Machine; - Sii->Executable = ImageSectionObject->Executable; + Status = _SEH_GetExceptionCode(); } - *ResultLength = sizeof(SECTION_IMAGE_INFORMATION); - Status = STATUS_SUCCESS; + _SEH_END; + break; } + }
- default: - *ResultLength = 0; - Status = STATUS_INVALID_INFO_CLASS; + ObDereferenceObject(Section); } - ObDereferenceObject(Section); + return(Status); }
@@ -3964,7 +4133,6 @@ * * @return Status. * - * @todo Guard by SEH. * @todo Move the actual code to internal function MmExtendSection. * @unimplemented */ @@ -3972,13 +4140,40 @@ NtExtendSection(IN HANDLE SectionHandle, IN PLARGE_INTEGER NewMaximumSize) { + LARGE_INTEGER SafeNewMaximumSize; PSECTION_OBJECT Section; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(NewMaximumSize, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + /* make a copy on the stack */ + SafeNewMaximumSize = *NewMaximumSize; + NewMaximumSize = &SafeNewMaximumSize; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + }
Status = ObReferenceObjectByHandle(SectionHandle, SECTION_EXTEND_SIZE, MmSectionObjectType, - UserMode, + PreviousMode, (PVOID*)&Section, NULL); if (!NT_SUCCESS(Status))