[KMTESTS]
authorThomas Faber <thomas.faber@reactos.org>
Sun, 11 Sep 2011 11:22:00 +0000 (11:22 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sun, 11 Sep 2011 11:22:00 +0000 (11:22 +0000)
- 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

12 files changed:
rostests/kmtests/CMakeLists.txt
rostests/kmtests/example/GuardedMemory.c [new file with mode: 0644]
rostests/kmtests/include/kmt_test.h
rostests/kmtests/kmtest.rbuild
rostests/kmtests/kmtest_drv.rbuild
rostests/kmtests/kmtest_drv/testlist.c
rostests/kmtests/ntos_ex/ExDoubleList.c
rostests/kmtests/ntos_ex/ExSequencedList.c
rostests/kmtests/ntos_ex/ExSingleList.c
rostests/kmtests/ntos_ke/KeIrql.c
rostests/kmtests/ntos_mm/MmSection.c [new file with mode: 0644]
rostests/kmtests/readme.txt

index b505697..310d342 100644 (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}
diff --git a/rostests/kmtests/example/GuardedMemory.c b/rostests/kmtests/example/GuardedMemory.c
new file mode 100644 (file)
index 0000000..766b568
--- /dev/null
@@ -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);
+}
index 73ea959..e187e05 100644 (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_ */
index 67c3f0b..6284980 100644 (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>
index 3adc67b..d9789a2 100644 (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>
index b17ad79..4fffe48 100644 (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 },
index d27993f..d2da26c 100644 (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>
 
index 1fad761..8f148f6 100644 (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
 }
index cebf265..d786ec7 100644 (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>
 
index 27c4d36..82082cf 100644 (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>
 
diff --git a/rostests/kmtests/ntos_mm/MmSection.c b/rostests/kmtests/ntos_mm/MmSection.c
new file mode 100644 (file)
index 0000000..96246b2
--- /dev/null
@@ -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);
+}
index fa9a66b..7a328b5 100644 (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.