https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e46c2dd1b301c72e70f89d1ab94ebaba2e95c93b

commit e46c2dd1b301c72e70f89d1ab94ebaba2e95c93b
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Wed Feb 10 15:21:55 2021 +0100
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Wed Feb 10 17:48:30 2021 +0100

    [VIDEOPRT] Mark low memory range as NOACCESS when we don't need to access 
it.
    
    This allows to accomplish great things, such as crashing when dereferencing 
NULL pointer.
---
 win32ss/drivers/videoprt/int10.c | 68 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/win32ss/drivers/videoprt/int10.c b/win32ss/drivers/videoprt/int10.c
index caa50ddfc35..2cf9b7fc590 100644
--- a/win32ss/drivers/videoprt/int10.c
+++ b/win32ss/drivers/videoprt/int10.c
@@ -23,12 +23,63 @@
 
 #include <ndk/kefuncs.h>
 #include <ndk/halfuncs.h>
+#include <ndk/mmfuncs.h>
 
 #define NDEBUG
 #include <debug.h>
 
 /* PRIVATE FUNCTIONS 
**********************************************************/
 
+#define IsLowV86Mem(_Seg, _Off) ((((_Seg) << 4) + (_Off)) < (0xa0000))
+
+/* Those two functions below are there so that CSRSS can't access low mem.
+ * Expecially, MAKE IT CRASH ON NULL ACCESS */
+static
+VOID
+ProtectLowV86Mem(VOID)
+{
+    /* We pass a non-NULL address so that ZwAllocateVirtualMemory really does 
it
+     * And we truncate one page to get the right range spanned. */
+    PVOID BaseAddress = (PVOID)1;
+    NTSTATUS Status;
+    SIZE_T ViewSize = 0xa0000 - PAGE_SIZE;
+
+    /* We should only do that for CSRSS. */
+    ASSERT(PsGetCurrentProcess() == (PEPROCESS)CsrProcess);
+
+    /* Commit (again) the pages, but with PAGE_NOACCESS protection */
+    Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+                                     &BaseAddress,
+                                     0,
+                                     &ViewSize,
+                                     MEM_COMMIT,
+                                     PAGE_NOACCESS);
+    ASSERT(NT_SUCCESS(Status));
+}
+
+static
+VOID
+UnprotectLowV86Mem(VOID)
+{
+    /* We pass a non-NULL address so that ZwAllocateVirtualMemory really does 
it
+     * And we truncate one page to get the right range spanned. */
+    PVOID BaseAddress = (PVOID)1;
+    NTSTATUS Status;
+    SIZE_T ViewSize = 0xa0000 - PAGE_SIZE;
+
+    /* We should only do that for CSRSS, for the v86 address space */
+    ASSERT(PsGetCurrentProcess() == (PEPROCESS)CsrProcess);
+
+    /* Commit (again) the pages, but with PAGE_READWRITE protection */
+    Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+                                     &BaseAddress,
+                                     0,
+                                     &ViewSize,
+                                     MEM_COMMIT,
+                                     PAGE_READWRITE);
+    ASSERT(NT_SUCCESS(Status));
+}
+
 #if defined(_M_IX86) || defined(_M_AMD64)
 NTSTATUS
 NTAPI
@@ -137,6 +188,9 @@ IntInitializeVideoAddressSpace(VOID)
     }
 #endif // _M_IX86
 
+    /* Protect the V86 address space after this */
+    ProtectLowV86Mem();
+
     /* Return success */
     return STATUS_SUCCESS;
 }
@@ -172,6 +226,7 @@ IntInt10AllocateBuffer(
 
     Size = *Length;
     MemoryAddress = (PVOID)0x20000;
+
     Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
                                      &MemoryAddress,
                                      0,
@@ -266,7 +321,13 @@ IntInt10ReadMemory(
     INFO_(VIDEOPRT, "- Length: %x\n", Length);
 
     IntAttachToCSRSS(&CallingProcess, &ApcState);
+
+    if (IsLowV86Mem(Seg, Off))
+        UnprotectLowV86Mem();
     RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)(Seg << 4) | Off), Length);
+    if (IsLowV86Mem(Seg, Off))
+        ProtectLowV86Mem();
+
     IntDetachFromCSRSS(&CallingProcess, &ApcState);
 
     return NO_ERROR;
@@ -298,7 +359,11 @@ IntInt10WriteMemory(
     INFO_(VIDEOPRT, "- Length: %x\n", Length);
 
     IntAttachToCSRSS(&CallingProcess, &ApcState);
+    if (IsLowV86Mem(Seg, Off))
+        UnprotectLowV86Mem();
     RtlCopyMemory((PVOID)((ULONG_PTR)(Seg << 4) | Off), Buffer, Length);
+    if (IsLowV86Mem(Seg, Off))
+        ProtectLowV86Mem();
     IntDetachFromCSRSS(&CallingProcess, &ApcState);
 
     return NO_ERROR;
@@ -349,11 +414,14 @@ IntInt10CallBios(
                                FALSE,
                                NULL);
 
+    /* The kernel needs access here */
+    UnprotectLowV86Mem();
 #ifdef _M_AMD64
     Status = x86BiosCall(0x10, &BiosContext) ? STATUS_SUCCESS : 
STATUS_UNSUCCESSFUL;
 #else
     Status = Ke386CallBios(0x10, &BiosContext);
 #endif
+    ProtectLowV86Mem();
 
     KeReleaseMutex(&VideoPortInt10Mutex, FALSE);
 

Reply via email to