1

Question:

For context, my code is meant to take a process and intentionally cause extra page faults. I start by manually modifying its page table entries' pte_flags by turning off their present bit and then turning on my own special bit, residing in the _PAGE_SOFTW2 page flag bit (arch/x86/include/asm/pgtable_types.h), to mark that I've messed with the pte.

This will cause a page fault later if the page is accessed again. As soon as this happens, I immediately reset the bits so that the page is marked present. Occasionally, my reset does not seem to last even in the next function call.

Any ideas why my bit modifications do not last?

Code samples:

Here is how I'm resetting bits after using walk_page_range() from mm/pagewalk.c:

set_pte(pte, pte_set_flags(*pte, _PAGE_PRESENT));       
set_pte(pte, pte_clear_flags(*pte,_PAGE_MY_BIT));

Here is one sample of printk statements demonstrating the issue.

// In do_page_fault I detect that my _PAGE_MY_BIT is set in the flags and flip it (424 -> 25)
[   44.473337] 1636 mpv/lua script  do_page_fault: Before: address 5555556acd30 pte 3f274c424 flags 424 
[   44.474116] 1636 mpv/lua script  do_page_fault: After: address 5555556acd30 pte 3f274c025 flags 25

// Just a few lines later, do_page_fault calls do_user_addr_fault and I print the same pte_flag
[   44.474950] 1636 mpv/lua script do_user_addr_fault: address 5555556acd30 pte 3f274c424 flags 424 

do_page_fault in arch/x86/mm/fault.c:

prefetchw(&current->mm->mmap_sem);
trace_page_fault_entries(regs, hw_error_code, address);

if (unlikely(kmmio_fault(regs, address)))
    return;

reset_the_pte(current, address, __func__);   // My function to flip the bits

/* Was the fault on kernel-controlled part of the address space? */
if (unlikely(fault_in_kernel_space(address)))
    do_kern_addr_fault(regs, hw_error_code, address);
else
    do_user_addr_fault(pte, regs, hw_error_code, address);

Possible answers:

1) According to this, ptes can be modified using pte_modify instead of pte_set_flags. Is that a better method or do they both have the same functionality with pte_modify being slightly more restrictive?

2) Could there be a context switch to another process between my reset function and do_user_addr_fault that could affect my pte somehow?

3) If this pte/page were shared memory with another process, would that affect my reset?

wxz
  • 2,254
  • 1
  • 10
  • 31
  • Haven't had a chance to test it out, but there's a chance I may also have to modify page flags in the struct page->flags (more info about page->flags in include/linux/page_flags.h) in addition to the pte flags themselves. – wxz Sep 09 '20 at 04:46

0 Answers0