https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a00378a1a1a1c12917ffa6...
commit a00378a1a1a1c12917ffa629da3a052c07fd7e4a Author: Timo Kreuzer timo.kreuzer@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);