|
@@ -1022,11 +1022,11 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
|
|
* routines.
|
|
* routines.
|
|
*/
|
|
*/
|
|
static void __kprobes
|
|
static void __kprobes
|
|
-__do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|
|
|
|
|
+__do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|
|
|
+ unsigned long address)
|
|
{
|
|
{
|
|
struct vm_area_struct *vma;
|
|
struct vm_area_struct *vma;
|
|
struct task_struct *tsk;
|
|
struct task_struct *tsk;
|
|
- unsigned long address;
|
|
|
|
struct mm_struct *mm;
|
|
struct mm_struct *mm;
|
|
int fault;
|
|
int fault;
|
|
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
|
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
|
@@ -1034,9 +1034,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|
tsk = current;
|
|
tsk = current;
|
|
mm = tsk->mm;
|
|
mm = tsk->mm;
|
|
|
|
|
|
- /* Get the faulting address: */
|
|
|
|
- address = read_cr2();
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Detect and handle instructions that would cause a page fault for
|
|
* Detect and handle instructions that would cause a page fault for
|
|
* both a tracked kernel page and a userspace page.
|
|
* both a tracked kernel page and a userspace page.
|
|
@@ -1252,9 +1249,11 @@ dotraplinkage void __kprobes
|
|
do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|
do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|
{
|
|
{
|
|
enum ctx_state prev_state;
|
|
enum ctx_state prev_state;
|
|
|
|
+ /* Get the faulting address: */
|
|
|
|
+ unsigned long address = read_cr2();
|
|
|
|
|
|
prev_state = exception_enter();
|
|
prev_state = exception_enter();
|
|
- __do_page_fault(regs, error_code);
|
|
|
|
|
|
+ __do_page_fault(regs, error_code, address);
|
|
exception_exit(prev_state);
|
|
exception_exit(prev_state);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1271,9 +1270,16 @@ dotraplinkage void __kprobes
|
|
trace_do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|
trace_do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|
{
|
|
{
|
|
enum ctx_state prev_state;
|
|
enum ctx_state prev_state;
|
|
|
|
+ /*
|
|
|
|
+ * The exception_enter and tracepoint processing could
|
|
|
|
+ * trigger another page faults (user space callchain
|
|
|
|
+ * reading) and destroy the original cr2 value, so read
|
|
|
|
+ * the faulting address now.
|
|
|
|
+ */
|
|
|
|
+ unsigned long address = read_cr2();
|
|
|
|
|
|
prev_state = exception_enter();
|
|
prev_state = exception_enter();
|
|
trace_page_fault_entries(regs, error_code);
|
|
trace_page_fault_entries(regs, error_code);
|
|
- __do_page_fault(regs, error_code);
|
|
|
|
|
|
+ __do_page_fault(regs, error_code, address);
|
|
exception_exit(prev_state);
|
|
exception_exit(prev_state);
|
|
}
|
|
}
|