Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass page fault code to Mm(Arm)AccessFault and implement NX support #256

Merged
merged 6 commits into from Jan 6, 2018

Conversation

tkreuzer
Copy link
Contributor

@tkreuzer tkreuzer commented Jan 1, 2018

This PR fixes the parameter passing to Mm(Arm)AccessFault and also implements support for NX faults where the architecture supports it (x64 and x86+PAE).

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.

@tkreuzer tkreuzer self-assigned this Jan 1, 2018
//#define MI_IS_NOT_PRESENT_FAULT(FaultCode) !BooleanFlagOn(FaultCode, 0x1)
//#define MI_IS_PROTECTION_FAULT(FaultCode) BooleanFlagOn(FaultCode, 0x1)
#define MI_IS_WRITE_ACCESS(FaultCode) BooleanFlagOn(FaultCode, 0x2)
//#define MI_IS_SUPERVISOR_ACCESS(FaultCode) BooleanFlagOn(FaultCode, 0x4)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing !

//#define MI_IS_NOT_PRESENT_FAULT(FaultCode) !BooleanFlagOn(FaultCode, 0x1)
//#define MI_IS_PROTECTION_FAULT(FaultCode) BooleanFlagOn(FaultCode, 0x1)
#define MI_IS_WRITE_ACCESS(FaultCode) BooleanFlagOn(FaultCode, 0x2)
//#define MI_IS_SUPERVISOR_ACCESS(FaultCode) BooleanFlagOn(FaultCode, 0x4)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one too, of course.

@@ -1776,6 +1777,17 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
11);
}
}

/* Check for execution of non-executable memory */
if ((MI_IS_INSTRUCTION_FETCH(FaultCode)) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for double parentheses?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol

@@ -1339,7 +1339,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
NotSListFault:

/* Call the access fault handler */
Status = MmAccessFault(Present,
Status = MmAccessFault(TrapFrame->ErrCode,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Present is unused now.

}

/* Keep same old ReactOS Behaviour */
if (StoreInstruction)
if (MI_IS_WRITE_ACCESS(FaultCode))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be !MI_IS_NOT_PRESENT_FAULT unless you're planning on changing the semantics

IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation)
{
KIRQL OldIrql = KeGetCurrentIrql(), LockIrql;
BOOLEAN StoreInstruction = MI_IS_WRITE_ACCESS(FaultCode);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also a semantic change, albeit one that makes the code behave as it should. But perhaps start with "present fault" here and make it a "write access" check in its own commit for easier regression testing?

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.
…te it there to what was declared as "StoreInstruction"

No functional changes.
@@ -1325,7 +1333,7 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
}

/* Resolve the fault -- this will release the PFN lock */
Status = MiResolveProtoPteFault(StoreInstruction,
Status = MiResolveProtoPteFault(!MI_IS_NOT_PRESENT_FAULT(FaultCode),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to mark these with a FIXME or something (since presumably they're meant to check for write instead)?

@tkreuzer tkreuzer merged commit 1014d50 into reactos:master Jan 6, 2018
@tkreuzer tkreuzer deleted the amd64/pagefault_NX branch April 2, 2019 11:13
@tkreuzer tkreuzer added this to the x64 bringup milestone Oct 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants