Note: before we had a BOOLEAN parameter called StoreInstruction, but in reality it was not specifying whether the fault was from a store store instruction, but whether it was an access violation rather than a page-not-present fault. On x86 without PAE there are only 2 kinds of access violations: (1) Access of a kernel mode page from user mode, which is handled early and (2) access of a read-only (or COW) page with a writing instruction. Therefore we could get away with this, even though it relied on the wrong assumption that a fault, which was not a page-not-present-fault, was automatically a write access. This commit only changes one thing: we pass the full fault-code to MmAccessFault and handle the rest from there in exactly the same way as before. More changes are coming to make things clear.
#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.Writable = 1)
#endif
#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.Writable = 1)
#endif
+/* Macros to identify the page fault reason from the error code */
+#define MI_IS_NOT_PRESENT_FAULT(FaultCode) !BooleanFlagOn(FaultCode, 0x1)
+
/* On x64, these are the same */
#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
#define ValidKernelPpe ValidKernelPde
/* On x64, these are the same */
#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
#define ValidKernelPpe ValidKernelPde
#define MI_MAKE_OWNER_PAGE(x) ((x)->u.Hard.Owner = 1)
#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.ReadOnly = 0)
#define MI_MAKE_OWNER_PAGE(x) ((x)->u.Hard.Owner = 1)
#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.ReadOnly = 0)
+/* Macros to identify the page fault reason from the error code */
+#define MI_IS_NOT_PRESENT_FAULT(FaultCode) TRUE
+
/* Convert an address to a corresponding PTE */
#define MiAddressToPte(x) \
((PMMPTE)(PTE_BASE + (((ULONG)(x) >> 12) << 2)))
/* Convert an address to a corresponding PTE */
#define MiAddressToPte(x) \
((PMMPTE)(PTE_BASE + (((ULONG)(x) >> 12) << 2)))
#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.Writable = 1)
#endif
#define MI_MAKE_WRITE_PAGE(x) ((x)->u.Hard.Writable = 1)
#endif
+
+/* Macros to identify the page fault reason from the error code */
+#define MI_IS_NOT_PRESENT_FAULT(FaultCode) !BooleanFlagOn(FaultCode, 0x1)
+
/* On x86, these two are the same */
#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
/* On x86, these two are the same */
#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
NTSTATUS
NTAPI
MmAccessFault(
NTSTATUS
NTAPI
MmAccessFault(
- IN BOOLEAN StoreInstruction,
IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation
IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation
sti
/* Call page fault handler */
sti
/* Call page fault handler */
- mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // StoreInstruction
- and ecx, 1
+ mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // FaultCode
// rdx == Address
mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode
and r8b, 1
// rdx == Address
mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode
and r8b, 1
//
if (KeArmFaultStatusRegisterGet() == 21 || KeArmFaultStatusRegisterGet() == 23)
{
//
if (KeArmFaultStatusRegisterGet() == 21 || KeArmFaultStatusRegisterGet() == 23)
{
- Status = MmAccessFault(FALSE,
+ Status = MmAccessFault(KeArmFaultStatusRegisterGet(),
Address,
KiGetPreviousMode(TrapFrame),
TrapFrame);
Address,
KiGetPreviousMode(TrapFrame),
TrapFrame);
KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
{
PKTHREAD Thread;
KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
{
PKTHREAD Thread;
BOOLEAN StoreInstruction;
ULONG_PTR Cr2;
NTSTATUS Status;
BOOLEAN StoreInstruction;
ULONG_PTR Cr2;
NTSTATUS Status;
_enable();
/* Interpret the error code */
_enable();
/* Interpret the error code */
- Present = (TrapFrame->ErrCode & 1) != 0;
StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
/* Check if we came in with interrupts disabled */
StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
/* Check if we came in with interrupts disabled */
KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
Cr2,
(ULONG_PTR)-1,
KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
Cr2,
(ULONG_PTR)-1,
TrapFrame->Eip,
TrapFrame);
}
TrapFrame->Eip,
TrapFrame);
}
NotSListFault:
/* Call the access fault handler */
NotSListFault:
/* Call the access fault handler */
- Status = MmAccessFault(Present,
+ Status = MmAccessFault(TrapFrame->ErrCode,
(PVOID)Cr2,
KiUserTrap(TrapFrame),
TrapFrame);
(PVOID)Cr2,
KiUserTrap(TrapFrame),
TrapFrame);
-MmAccessFault(IN BOOLEAN StoreInstruction,
+MmAccessFault(IN ULONG FaultCode,
IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation)
{
PMEMORY_AREA MemoryArea = NULL;
IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation)
{
PMEMORY_AREA MemoryArea = NULL;
+ BOOLEAN StoreInstruction = !MI_IS_NOT_PRESENT_FAULT(FaultCode);
/* Cute little hack for ROS */
if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)
/* Cute little hack for ROS */
if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)