64bit

手動設置特定 PTE 的 NX 位

  • December 20, 2018

在核心 4.16.7 的 Ubuntu 上,我正在編寫一個自定義系統呼叫,並且我想設置特定頁表條目的 NX 位。到目前為止,我有這段程式碼,我正在執行頁表遍歷以獲得我想要的 PTE,然後嘗試設置它的 NX 位:

pgd = pgd_offset(mm, addr);
if (pgd_none(*pgd) || pgd_bad(*pgd)){
   printk("Invalid pgd");
   return -1;
}

p4d = p4d_offset(pgd, addr);
if (p4d_none(*p4d) || p4d_bad(*p4d)){
   printk("Invalid p4d");
   return -1;
}

pud = pud_offset(p4d, addr);
if (pud_none(*pud) || pud_bad(*pud)){
   printk("Invalid pud");
   return -1;
}

pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd)){
   printk("Invalid pmd");
   return -1;
}

ptep = pte_offset_map(pmd, addr);
if (!ptep){
   printk("Invalid ptep");
   return -1;
}
pte = *ptep;

if (pte_present(pte)){
   printk("pte_set_flags");
   printk("NX bit before:  %d", pte_exec(pte));
   // pte_set_flags(pte, _PAGE_NX);
   // printk("NX bit after :  %d", pte_exec(pte));
   printk("pte_clear_flags");
   // pte_clear_flags(pte, _PAGE_NX); // Same as pte_mkexec()
   pte_mkexec(pte);
   printk("NX bit after :  %d", pte_exec(pte));
   page = pte_page(pte);
   if (page){
       printk("Page frame struct is @ %p", page);
   }

   pte_unmap(ptep);
}

但它不起作用。所有printk命令都顯示相同的結果。有什麼見解嗎?

所以我自己找到了。程式碼如下:

struct vm_area_struct *vma;
unsigned long oldflags, newflags, pfn;

vma = find_extend_vma(mm, addr);
oldflags = vma->vm_flags;
newflags = oldflags &= ~VM_EXEC;

//...
//...
//...

if (pte_present(pte)){
   printk("NX bit before: %d", pte_exec(pte));

   pte = pte_modify(pte, vm_get_page_prot(newflags));
   printk("NX bit after:  %d", pte_exec(pte));

   pfn = pte_pfn(pte);

   flush_cache_page(vma, addr, pfn);
   set_pte(ptep, pte);
   flush_tlb_page(vma, addr);
   update_mmu_cache(vma, addr, ptep);

   pte_unmap(ptep);
}

因此特定 PTE 的 NX 位被改變。

引用自:https://unix.stackexchange.com/questions/461234