[NTOS:MM] Add support for NX page-faults
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Tue, 2 Jan 2018 10:22:22 +0000 (11:22 +0100)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 6 Jan 2018 17:20:24 +0000 (18:20 +0100)
ntoskrnl/include/internal/amd64/mm.h
ntoskrnl/include/internal/arm/mm.h
ntoskrnl/include/internal/i386/mm.h
ntoskrnl/mm/ARM3/pagfault.c

index d2769fd..3b0b217 100644 (file)
@@ -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)
 /* 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
index 0d08a55..0e2e79d 100644 (file)
@@ -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) \
index 573de1e..7d5c5ed 100644 (file)
 #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)
 /* 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
index e5225fd..71c8ea6 100644 (file)
@@ -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);