secured buffer access in NtCreateSection(), NtOpenSection(), NtMapViewOfSection(), NtQuerySection() and NtExtendSection()

svn path=/trunk/; revision=13583
This commit is contained in:
Thomas Bluemel 2005-02-15 15:46:22 +00:00
parent a2e0ee8993
commit 382d68525a
2 changed files with 286 additions and 91 deletions

View file

@ -5420,10 +5420,10 @@ NTSTATUS
STDCALL STDCALL
NtQuerySection( NtQuerySection(
IN HANDLE SectionHandle, IN HANDLE SectionHandle,
IN CINT SectionInformationClass, IN SECTION_INFORMATION_CLASS SectionInformationClass,
OUT PVOID SectionInformation, OUT PVOID SectionInformation,
IN ULONG Length, IN ULONG SectionInformationLength,
OUT PULONG ResultLength OUT PULONG ResultLength OPTIONAL
); );
/* /*
@ -6451,10 +6451,10 @@ NTSTATUS
STDCALL STDCALL
ZwQuerySection( ZwQuerySection(
IN HANDLE SectionHandle, IN HANDLE SectionHandle,
IN CINT SectionInformationClass, IN SECTION_INFORMATION_CLASS SectionInformationClass,
OUT PVOID SectionInformation, OUT PVOID SectionInformation,
IN ULONG Length, IN ULONG SectionInformationLength,
OUT PULONG ResultLength OUT PULONG ResultLength OPTIONAL
); );
typedef struct _SECTION_IMAGE_INFORMATION typedef struct _SECTION_IMAGE_INFORMATION

View file

@ -50,6 +50,12 @@ static GENERIC_MAPPING MmpSectionMapping = {
#define SWAPENTRY_FROM_SSE(E) ((E) >> 1) #define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
#define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1) #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 *****************************************************************/ /* FUNCTIONS *****************************************************************/
/* Note: Mmsp prefix denotes "Memory Manager Section Private". */ /* Note: Mmsp prefix denotes "Memory Manager Section Private". */
@ -3309,9 +3315,36 @@ NtCreateSection (OUT PHANDLE SectionHandle,
IN ULONG AllocationAttributes, IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL) IN HANDLE FileHandle OPTIONAL)
{ {
LARGE_INTEGER SafeMaximumSize;
PSECTION_OBJECT SectionObject; 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 * Check the protection
*/ */
@ -3367,17 +3400,52 @@ NtOpenSection(PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes) POBJECT_ATTRIBUTES ObjectAttributes)
{ {
NTSTATUS Status; HANDLE hSection;
KPROCESSOR_MODE PreviousMode;
*SectionHandle = 0; 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;
}
}
Status = ObOpenObjectByName(ObjectAttributes, Status = ObOpenObjectByName(ObjectAttributes,
MmSectionObjectType, MmSectionObjectType,
NULL, NULL,
UserMode, PreviousMode,
DesiredAccess, DesiredAccess,
NULL, NULL,
SectionHandle); &hSection);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*SectionHandle = hSection;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return(Status); return(Status);
} }
@ -3487,26 +3555,77 @@ MmMapViewOfSegment(PEPROCESS Process,
* @implemented * @implemented
*/ */
NTSTATUS STDCALL NTSTATUS STDCALL
NtMapViewOfSection(HANDLE SectionHandle, NtMapViewOfSection(IN HANDLE SectionHandle,
HANDLE ProcessHandle, IN HANDLE ProcessHandle,
PVOID* BaseAddress, IN OUT PVOID* BaseAddress OPTIONAL,
ULONG ZeroBits, IN ULONG ZeroBits OPTIONAL,
ULONG CommitSize, IN ULONG CommitSize,
PLARGE_INTEGER SectionOffset, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
PULONG ViewSize, IN OUT PULONG ViewSize,
SECTION_INHERIT InheritDisposition, IN SECTION_INHERIT InheritDisposition,
ULONG AllocationType, IN ULONG AllocationType OPTIONAL,
ULONG Protect) IN ULONG Protect)
{ {
PVOID SafeBaseAddress;
LARGE_INTEGER SafeSectionOffset;
ULONG SafeViewSize;
PSECTION_OBJECT Section; PSECTION_OBJECT Section;
PEPROCESS Process; PEPROCESS Process;
NTSTATUS Status; KPROCESSOR_MODE PreviousMode;
PMADDRESS_SPACE AddressSpace; 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, Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_OPERATION, PROCESS_VM_OPERATION,
PsProcessType, PsProcessType,
UserMode, PreviousMode,
(PVOID*)(PVOID)&Process, (PVOID*)(PVOID)&Process,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -3519,7 +3638,7 @@ NtMapViewOfSection(HANDLE SectionHandle,
Status = ObReferenceObjectByHandle(SectionHandle, Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_MAP_READ, SECTION_MAP_READ,
MmSectionObjectType, MmSectionObjectType,
UserMode, PreviousMode,
(PVOID*)(PVOID)&Section, (PVOID*)(PVOID)&Section,
NULL); NULL);
if (!(NT_SUCCESS(Status))) if (!(NT_SUCCESS(Status)))
@ -3531,17 +3650,42 @@ NtMapViewOfSection(HANDLE SectionHandle,
Status = MmMapViewOfSection(Section, Status = MmMapViewOfSection(Section,
Process, Process,
BaseAddress, (BaseAddress != NULL ? &SafeBaseAddress : NULL),
ZeroBits, ZeroBits,
CommitSize, CommitSize,
SectionOffset, (SectionOffset != NULL ? &SafeSectionOffset : NULL),
ViewSize, (ViewSize != NULL ? &SafeViewSize : NULL),
InheritDisposition, InheritDisposition,
AllocationType, AllocationType,
Protect); Protect);
ObDereferenceObject(Section); ObDereferenceObject(Section);
ObDereferenceObject(Process); 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); return(Status);
} }
@ -3809,16 +3953,19 @@ NtUnmapViewOfSection (HANDLE ProcessHandle,
PVOID BaseAddress) PVOID BaseAddress)
{ {
PEPROCESS Process; PEPROCESS Process;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status; NTSTATUS Status;
DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n", DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n",
ProcessHandle, BaseAddress); ProcessHandle, BaseAddress);
PreviousMode = ExGetPreviousMode();
DPRINT("Referencing process\n"); DPRINT("Referencing process\n");
Status = ObReferenceObjectByHandle(ProcessHandle, Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_OPERATION, PROCESS_VM_OPERATION,
PsProcessType, PsProcessType,
UserMode, PreviousMode,
(PVOID*)(PVOID)&Process, (PVOID*)(PVOID)&Process,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -3857,98 +4004,120 @@ NtUnmapViewOfSection (HANDLE ProcessHandle,
* *
* @return Status. * @return Status.
* *
* @todo Guard by SEH.
* @implemented * @implemented
*/ */
NTSTATUS STDCALL NTSTATUS STDCALL
NtQuerySection(IN HANDLE SectionHandle, NtQuerySection(IN HANDLE SectionHandle,
IN CINT SectionInformationClass, IN SECTION_INFORMATION_CLASS SectionInformationClass,
OUT PVOID SectionInformation, OUT PVOID SectionInformation,
IN ULONG Length, IN ULONG SectionInformationLength,
OUT PULONG ResultLength) OUT PULONG ResultLength OPTIONAL)
{ {
PSECTION_OBJECT Section; 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, Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_QUERY, SECTION_QUERY,
MmSectionObjectType, MmSectionObjectType,
UserMode, PreviousMode,
(PVOID*)(PVOID)&Section, (PVOID*)(PVOID)&Section,
NULL); 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); Sbi->Attributes = Section->AllocationAttributes;
return(STATUS_INFO_LENGTH_MISMATCH); 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;
}
if (ResultLength != NULL)
{
*ResultLength = sizeof(SECTION_BASIC_INFORMATION);
}
Status = STATUS_SUCCESS;
} }
_SEH_HANDLE
Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
Sbi->Attributes = Section->AllocationAttributes;
if (Section->AllocationAttributes & SEC_IMAGE)
{ {
Sbi->BaseAddress = 0; Status = _SEH_GetExceptionCode();
Sbi->Size.QuadPart = 0;
} }
else _SEH_END;
{
Sbi->BaseAddress = (PVOID)Section->Segment->VirtualAddress;
Sbi->Size.QuadPart = Section->Segment->Length;
}
*ResultLength = sizeof(SECTION_BASIC_INFORMATION);
Status = STATUS_SUCCESS;
break; 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); memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION));
return(STATUS_INFO_LENGTH_MISMATCH); if (Section->AllocationAttributes & SEC_IMAGE)
} {
PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
ImageSectionObject = Section->ImageSection;
Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation; Sii->EntryPoint = ImageSectionObject->EntryPoint;
memset(Sii, 0, sizeof(SECTION_IMAGE_INFORMATION)); Sii->StackReserve = ImageSectionObject->StackReserve;
if (Section->AllocationAttributes & SEC_IMAGE) 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;
}
_SEH_HANDLE
{ {
PMM_IMAGE_SECTION_OBJECT ImageSectionObject; Status = _SEH_GetExceptionCode();
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;
} }
*ResultLength = sizeof(SECTION_IMAGE_INFORMATION); _SEH_END;
Status = STATUS_SUCCESS;
break; break;
} }
}
default: ObDereferenceObject(Section);
*ResultLength = 0;
Status = STATUS_INVALID_INFO_CLASS;
} }
ObDereferenceObject(Section);
return(Status); return(Status);
} }
@ -3964,7 +4133,6 @@ NtQuerySection(IN HANDLE SectionHandle,
* *
* @return Status. * @return Status.
* *
* @todo Guard by SEH.
* @todo Move the actual code to internal function MmExtendSection. * @todo Move the actual code to internal function MmExtendSection.
* @unimplemented * @unimplemented
*/ */
@ -3972,13 +4140,40 @@ NTSTATUS STDCALL
NtExtendSection(IN HANDLE SectionHandle, NtExtendSection(IN HANDLE SectionHandle,
IN PLARGE_INTEGER NewMaximumSize) IN PLARGE_INTEGER NewMaximumSize)
{ {
LARGE_INTEGER SafeNewMaximumSize;
PSECTION_OBJECT Section; 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, Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_EXTEND_SIZE, SECTION_EXTEND_SIZE,
MmSectionObjectType, MmSectionObjectType,
UserMode, PreviousMode,
(PVOID*)&Section, (PVOID*)&Section,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))