[KMTESTS]

- Add support for guarded allocations, that can be used to detect buffer overruns
- Add GuardedMemory example test
- Add MmSection test with some basic parameter checks for MmCreateSection
- Fix some x64 build problems
- Update readme

svn path=/trunk/; revision=53687
This commit is contained in:
Thomas Faber 2011-09-11 11:22:00 +00:00
parent 0d4f432270
commit 2b17fa159d
12 changed files with 223 additions and 2 deletions

View file

@ -8,6 +8,7 @@ add_subdirectory(example)
add_subdirectory(ntos_io)
list(APPEND COMMON_SOURCE
example/GuardedMemory.c
rtl/RtlAvlTree.c
rtl/RtlMemory.c
rtl/RtlSplayTree.c)
@ -42,6 +43,7 @@ list(APPEND KMTEST_DRV_SOURCE
ntos_ke/KeIrql.c
ntos_ke/KeProcessor.c
ntos_ke/KeSpinLock.c
ntos_mm/MmSection.c
ntos_ob/ObReference.c
ntos_ob/ObType.c
${COMMON_SOURCE}

View file

@ -0,0 +1,63 @@
/*
* PROJECT: ReactOS kernel-mode tests
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Kernel-Mode Test Suite Guarded Memory example test
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
*/
#include <kmt_test.h>
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wnonnull"
#endif /* defined __GNUC__ */
START_TEST(GuardedMemory)
{
NTSTATUS Status;
SIZE_T Size = 123;
PCHAR *Buffer;
/* access some invalid memory to test SEH */
Status = STATUS_SUCCESS;
_SEH2_TRY
{
RtlFillMemory(NULL, 1, 0);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
} _SEH2_END;
ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
/* get guarded mem */
Buffer = KmtAllocateGuarded(Size);
if (skip(Buffer != NULL, "Failed to allocate guarded memory\n"))
return;
/* access to guarded mem should be fine */
Status = STATUS_SUCCESS;
_SEH2_TRY
{
RtlFillMemory(Buffer, Size, 0);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
} _SEH2_END;
ok_eq_hex(Status, STATUS_SUCCESS);
/* access one byte behind guarded mem must cause an access violation! */
Status = STATUS_SUCCESS;
_SEH2_TRY
{
RtlFillMemory(Buffer + Size, 1, 0);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
} _SEH2_END;
ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
KmtFreeGuarded(Buffer);
}

View file

@ -129,6 +129,8 @@ VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments)
VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 2, 3);
BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
PVOID KmtAllocateGuarded(SIZE_T SizeRequested);
VOID KmtFreeGuarded(PVOID Pointer);
#ifdef KMT_KERNEL_MODE
#define ok_irql(irql) ok(KeGetCurrentIrql() == irql, "IRQL is %d, expected %d\n", KeGetCurrentIrql(), irql)
@ -411,6 +413,44 @@ BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
return Ret;
}
PVOID KmtAllocateGuarded(SIZE_T SizeRequested)
{
NTSTATUS Status;
SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
PVOID VirtualMemory = NULL;
PCHAR StartOfBuffer;
Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
if (!NT_SUCCESS(Status))
return NULL;
Size -= PAGE_SIZE;
Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
Size = 0;
Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
ok_eq_hex(Status, STATUS_SUCCESS);
return NULL;
}
StartOfBuffer = VirtualMemory;
StartOfBuffer += Size - SizeRequested;
return StartOfBuffer;
}
VOID KmtFreeGuarded(PVOID Pointer)
{
NTSTATUS Status;
PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
SIZE_T Size = 0;
Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
ok_eq_hex(Status, STATUS_SUCCESS);
}
#endif /* defined KMT_DEFINE_TEST_FUNCTIONS */
#endif /* !defined _KMTEST_TEST_H_ */

View file

@ -12,6 +12,7 @@
</directory>
<directory name="example">
<file>Example_user.c</file>
<file>GuardedMemory.c</file>
</directory>
<directory name="ntos_io">
<file>IoDeviceObject_user.c</file>

View file

@ -12,6 +12,7 @@
</directory>
<directory name="example">
<file>Example.c</file>
<file>GuardedMemory.c</file>
<file>KernelType.c</file>
</directory>
<directory name="ntos_ex">
@ -43,6 +44,9 @@
<file>KeProcessor.c</file>
<file>KeSpinLock.c</file>
</directory>
<directory name="ntos_mm">
<file>MmSection.c</file>
</directory>
<directory name="ntos_ob">
<file>ObReference.c</file>
<file>ObType.c</file>

View file

@ -30,6 +30,7 @@ KMT_TESTFUNC Test_KeGuardedMutex;
KMT_TESTFUNC Test_KeIrql;
KMT_TESTFUNC Test_KeProcessor;
KMT_TESTFUNC Test_KernelType;
KMT_TESTFUNC Test_MmSection;
KMT_TESTFUNC Test_ObReference;
KMT_TESTFUNC Test_ObType;
KMT_TESTFUNC Test_ObTypeClean;
@ -63,6 +64,7 @@ const KMT_TEST TestList[] =
{ "KeIrql", Test_KeIrql },
{ "-KeProcessor", Test_KeProcessor },
{ "-KernelType", Test_KernelType },
{ "MmSection", Test_MmSection },
{ "ObReference", Test_ObReference },
{ "ObType", Test_ObType },
{ "-ObTypeClean", Test_ObTypeClean },

View file

@ -6,9 +6,11 @@
*/
struct _LIST_ENTRY;
#ifdef _X86_
struct _LIST_ENTRY *__stdcall ExInterlockedInsertHeadList(struct _LIST_ENTRY *, struct _LIST_ENTRY *, unsigned long *);
struct _LIST_ENTRY *__stdcall ExInterlockedInsertTailList(struct _LIST_ENTRY *, struct _LIST_ENTRY *, unsigned long *);
struct _LIST_ENTRY *__stdcall ExInterlockedRemoveHeadList(struct _LIST_ENTRY *, unsigned long *);
#endif
#include <kmt_test.h>

View file

@ -13,7 +13,7 @@ struct _SINGLE_LIST_ENTRY *__fastcall ExInterlockedPopEntrySList(union _SLIST_HE
#include <kmt_test.h>
/* TODO: SLIST_HEADER is a lot different for x64 */
#ifndef _M_AMD64
#define CheckSListHeader(ListHead, ExpectedPointer, ExpectedDepth) do \
{ \
ok_eq_pointer((ListHead)->Next.Next, ExpectedPointer); \
@ -39,9 +39,11 @@ struct _SINGLE_LIST_ENTRY *__fastcall ExInterlockedPopEntrySList(union _SLIST_HE
#undef ExInterlockedPopEntrySList
#define TestXListFunctional TestSListFunctionalExports
#include "ExXList.h"
#endif
START_TEST(ExSequencedList)
{
#ifndef _M_AMD64
PSLIST_HEADER ListHead;
KSPIN_LOCK SpinLock;
USHORT ExpectedSequence = 0;
@ -76,4 +78,5 @@ START_TEST(ExSequencedList)
KeLowerIrql(Irql);
ExFreePoolWithTag(Buffer, 'TLqS');
#endif
}

View file

@ -6,8 +6,10 @@
*/
struct _SINGLE_LIST_ENTRY;
#ifdef _X86_
struct _SINGLE_LIST_ENTRY *__stdcall ExInterlockedPushEntryList(struct _SINGLE_LIST_ENTRY *, struct _SINGLE_LIST_ENTRY *, unsigned long *);
struct _SINGLE_LIST_ENTRY *__stdcall ExInterlockedPopEntryList(struct _SINGLE_LIST_ENTRY *, unsigned long *);
#endif
#include <kmt_test.h>

View file

@ -7,6 +7,10 @@
__declspec(dllimport) void __stdcall KeRaiseIrql(unsigned char, unsigned char *);
__declspec(dllimport) void __stdcall KeLowerIrql(unsigned char);
#ifdef _M_AMD64
#define CLOCK1_LEVEL CLOCK_LEVEL
#define CLOCK2_LEVEL CLOCK_LEVEL
#endif
#include <kmt_test.h>

View file

@ -0,0 +1,98 @@
/*
* PROJECT: ReactOS kernel-mode tests
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Kernel-Mode Test Suite Section Object test
* PROGRAMMER: Thomas Faber <thfabba@gmx.de>
*/
#include <kmt_test.h>
#define StartSeh() ExceptionStatus = STATUS_SUCCESS; _SEH2_TRY {
#define EndSeh(ExpectedStatus) } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExceptionStatus = _SEH2_GetExceptionCode(); } _SEH2_END; ok_eq_hex(ExceptionStatus, ExpectedStatus)
START_TEST(MmSection)
{
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS ExceptionStatus;
const PVOID InvalidPointer = (PVOID)0x5555555555555555LLU;
PVOID SectionObject;
LARGE_INTEGER MaximumSize;
StartSeh()
Status = MmCreateSection(NULL, 0, NULL, NULL, 0, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_SUCCESS);
ok_eq_hex(Status, STATUS_INVALID_PAGE_PROTECTION);
if (!KmtIsCheckedBuild)
{
/* PAGE_NOACCESS and missing SEC_RESERVE/SEC_COMMIT/SEC_IMAGE assert */
StartSeh()
Status = MmCreateSection(NULL, 0, NULL, NULL, PAGE_NOACCESS, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_ACCESS_VIOLATION);
StartSeh()
Status = MmCreateSection(NULL, 0, NULL, NULL, PAGE_NOACCESS, 0, NULL, NULL);
EndSeh(STATUS_ACCESS_VIOLATION);
}
SectionObject = InvalidPointer;
StartSeh()
Status = MmCreateSection(&SectionObject, 0, NULL, NULL, 0, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_SUCCESS);
ok_eq_hex(Status, STATUS_INVALID_PAGE_PROTECTION);
ok_eq_pointer(SectionObject, InvalidPointer);
StartSeh()
Status = MmCreateSection(NULL, 0, NULL, NULL, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_ACCESS_VIOLATION);
SectionObject = InvalidPointer;
StartSeh()
Status = MmCreateSection(&SectionObject, 0, NULL, NULL, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_ACCESS_VIOLATION);
ok_eq_pointer(SectionObject, InvalidPointer);
MaximumSize.QuadPart = 0;
StartSeh()
Status = MmCreateSection(NULL, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_SUCCESS);
ok_eq_hex(Status, STATUS_INVALID_PARAMETER_4);
ok_eq_longlong(MaximumSize.QuadPart, 0LL);
MaximumSize.QuadPart = 1;
StartSeh()
Status = MmCreateSection(NULL, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_ACCESS_VIOLATION);
ok_eq_longlong(MaximumSize.QuadPart, 1LL);
SectionObject = InvalidPointer;
MaximumSize.QuadPart = 0;
StartSeh()
Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_SUCCESS);
ok_eq_hex(Status, STATUS_INVALID_PARAMETER_4);
ok_eq_longlong(MaximumSize.QuadPart, 0LL);
ok_eq_pointer(SectionObject, InvalidPointer);
SectionObject = InvalidPointer;
MaximumSize.QuadPart = 1;
StartSeh()
Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_RESERVE, NULL, NULL);
EndSeh(STATUS_SUCCESS);
ok_eq_hex(Status, STATUS_SUCCESS);
ok_eq_longlong(MaximumSize.QuadPart, 1LL);
ok(SectionObject != InvalidPointer, "Section object pointer untouched\n");
ok(SectionObject != NULL, "Section object pointer NULL\n");
if (SectionObject && SectionObject != InvalidPointer)
ObDereferenceObject(SectionObject);
SectionObject = InvalidPointer;
MaximumSize.QuadPart = 1;
StartSeh()
Status = MmCreateSection(&SectionObject, 0, NULL, &MaximumSize, PAGE_READONLY, SEC_IMAGE, NULL, NULL);
EndSeh(STATUS_SUCCESS);
ok_eq_hex(Status, STATUS_INVALID_FILE_FOR_SECTION);
ok_eq_longlong(MaximumSize.QuadPart, 1LL);
ok_eq_pointer(SectionObject, InvalidPointer);
}

View file

@ -7,5 +7,5 @@ The example subdirectory contains a set of small tests that can be used as
examples and templates.
See http://www.reactos.org/wiki/User:ThFabba/KmtestsHowto for more
See http://www.reactos.org/wiki/KmtestsHowto for more
information and a guide on how to use the framework.