https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e46c2dd1b301c72e70f89…
commit e46c2dd1b301c72e70f89d1ab94ebaba2e95c93b
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Wed Feb 10 15:21:55 2021 +0100
Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com>
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);