mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
[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:
parent
0d4f432270
commit
2b17fa159d
|
@ -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}
|
||||
|
|
63
rostests/kmtests/example/GuardedMemory.c
Normal file
63
rostests/kmtests/example/GuardedMemory.c
Normal 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);
|
||||
}
|
|
@ -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_ */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
98
rostests/kmtests/ntos_mm/MmSection.c
Normal file
98
rostests/kmtests/ntos_mm/MmSection.c
Normal 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);
|
||||
}
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue