https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a00378a1a1a1c12917ffa…
commit a00378a1a1a1c12917ffa629da3a052c07fd7e4a
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Tue Jan 2 11:22:22 2018 +0100
[NTOS:MM] Add support for NX page-faults
---
ntoskrnl/include/internal/amd64/mm.h | 2 ++
ntoskrnl/include/internal/arm/mm.h | 2 ++
ntoskrnl/include/internal/i386/mm.h | 6 ++++++
ntoskrnl/mm/ARM3/pagfault.c | 31 ++++++++++++++++++++++++++++++-
4 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/ntoskrnl/include/internal/amd64/mm.h b/ntoskrnl/include/internal/amd64/mm.h
index d2769fd859..3b0b217bd9 100644
--- a/ntoskrnl/include/internal/amd64/mm.h
+++ b/ntoskrnl/include/internal/amd64/mm.h
@@ -98,6 +98,7 @@
#define MI_IS_PAGE_WRITEABLE(x) ((x)->u.Hard.Writable == 1)
#endif
#define MI_IS_PAGE_COPY_ON_WRITE(x)((x)->u.Hard.CopyOnWrite == 1)
+#define MI_IS_PAGE_EXECUTABLE(x) ((x)->u.Hard.NoExecute == 0)
#define MI_IS_PAGE_DIRTY(x) ((x)->u.Hard.Dirty == 1)
#define MI_MAKE_OWNER_PAGE(x) ((x)->u.Hard.Owner = 1)
#if !defined(CONFIG_SMP)
@@ -109,6 +110,7 @@
/* Macros to identify the page fault reason from the error code */
#define MI_IS_NOT_PRESENT_FAULT(FaultCode) !BooleanFlagOn(FaultCode, 0x1)
#define MI_IS_WRITE_ACCESS(FaultCode) BooleanFlagOn(FaultCode, 0x2)
+#define MI_IS_INSTRUCTION_FETCH(FaultCode) BooleanFlagOn(FaultCode, 0x10)
/* On x64, these are the same */
#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
diff --git a/ntoskrnl/include/internal/arm/mm.h b/ntoskrnl/include/internal/arm/mm.h
index 0d08a55cdf..0e2e79d15c 100644
--- a/ntoskrnl/include/internal/arm/mm.h
+++ b/ntoskrnl/include/internal/arm/mm.h
@@ -84,6 +84,7 @@
#define MI_IS_PAGE_LARGE(x) FALSE
#define MI_IS_PAGE_WRITEABLE(x) ((x)->u.Hard.ReadOnly == 0)
#define MI_IS_PAGE_COPY_ON_WRITE(x)FALSE
+#define MI_IS_PAGE_EXECUTABLE(x) TRUE
#define MI_IS_PAGE_DIRTY(x) TRUE
#define MI_MAKE_OWNER_PAGE(x) ((x)->u.Hard.Owner = 1)
#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.ReadOnly = 0)
@@ -91,6 +92,7 @@
/* Macros to identify the page fault reason from the error code */
#define MI_IS_NOT_PRESENT_FAULT(FaultCode) TRUE
#define MI_IS_WRITE_ACCESS(FaultCode) TRUE
+#define MI_IS_INSTRUCTION_FETCH(FaultCode) FALSE
/* Convert an address to a corresponding PTE */
#define MiAddressToPte(x) \
diff --git a/ntoskrnl/include/internal/i386/mm.h b/ntoskrnl/include/internal/i386/mm.h
index 573de1eb45..7d5c5ed667 100644
--- a/ntoskrnl/include/internal/i386/mm.h
+++ b/ntoskrnl/include/internal/i386/mm.h
@@ -103,6 +103,11 @@
#define MI_IS_PAGE_WRITEABLE(x) ((x)->u.Hard.Writable == 1)
#endif
#define MI_IS_PAGE_COPY_ON_WRITE(x)((x)->u.Hard.CopyOnWrite == 1)
+#ifdef _PAE_
+#define MI_IS_PAGE_EXECUTABLE(x) ((x)->u.Hard.NoExecute == 0)
+#else
+#define MI_IS_PAGE_EXECUTABLE(x) TRUE
+#endif
#define MI_IS_PAGE_DIRTY(x) ((x)->u.Hard.Dirty == 1)
#define MI_MAKE_OWNER_PAGE(x) ((x)->u.Hard.Owner = 1)
#if !defined(CONFIG_SMP)
@@ -115,6 +120,7 @@
/* Macros to identify the page fault reason from the error code */
#define MI_IS_NOT_PRESENT_FAULT(FaultCode) !BooleanFlagOn(FaultCode, 0x1)
#define MI_IS_WRITE_ACCESS(FaultCode) BooleanFlagOn(FaultCode, 0x2)
+#define MI_IS_INSTRUCTION_FETCH(FaultCode) BooleanFlagOn(FaultCode, 0x10)
/* On x86, these two are the same */
#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
diff --git a/ntoskrnl/mm/ARM3/pagfault.c b/ntoskrnl/mm/ARM3/pagfault.c
index e5225fd63b..71c8ea6b73 100644
--- a/ntoskrnl/mm/ARM3/pagfault.c
+++ b/ntoskrnl/mm/ARM3/pagfault.c
@@ -1780,6 +1780,17 @@ MmArmAccessFault(IN ULONG FaultCode,
11);
}
}
+
+ /* Check for execution of non-executable memory */
+ if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
+ !MI_IS_PAGE_EXECUTABLE(&TempPte))
+ {
+ KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
+ (ULONG_PTR)Address,
+ (ULONG_PTR)TempPte.u.Long,
+ (ULONG_PTR)TrapInformation,
+ 1);
+ }
}
/* Release PFN lock and return all good */
@@ -1886,6 +1897,17 @@ _WARN("Session space stuff is not implemented yet!")
}
}
+ /* Check for execution of non-executable memory */
+ if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
+ !MI_IS_PAGE_EXECUTABLE(&TempPte))
+ {
+ KeBugCheckEx(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY,
+ (ULONG_PTR)Address,
+ (ULONG_PTR)TempPte.u.Long,
+ (ULONG_PTR)TrapInformation,
+ 2);
+ }
+
/* Check for read-only write in session space */
if ((IsSessionAddress) &&
MI_IS_WRITE_ACCESS(FaultCode) &&
@@ -2196,7 +2218,14 @@ UserFault:
}
}
- /* FIXME: Execution is ignored for now, since we don't have no-execute pages
yet */
+ /* Check for execution of non-executable memory */
+ if (MI_IS_INSTRUCTION_FETCH(FaultCode) &&
+ !MI_IS_PAGE_EXECUTABLE(&TempPte))
+ {
+ /* Return the status */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return STATUS_ACCESS_VIOLATION;
+ }
/* The fault has already been resolved by a different thread */
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);