Commit df992848f5aa803fcacd2c5e7d67034bb89e3fa3

Authored by Andi Kleen
Committed by Andi Kleen
1 parent d3cf7f0615

[PATCH] Fix pte_exec/mkexec and use it in change_page_attr()

Fix the pte_exec/mkexec page table accessor functions to really
use the NX bit. Previously they only checked the USER bit, but
weren't actually used for anything.

Then use them in change_page_attr() to manipulate the NX bit
properly.

Signed-off-by: Andi Kleen <ak@suse.de>

Showing 2 changed files with 7 additions and 5 deletions Side-by-side Diff

arch/x86_64/mm/pageattr.c
... ... @@ -190,10 +190,12 @@
190 190 * lowmem */
191 191 if (__pa(address) < KERNEL_TEXT_SIZE) {
192 192 unsigned long addr2;
193   - pgprot_t prot2 = prot;
  193 + pgprot_t prot2;
194 194 addr2 = __START_KERNEL_map + __pa(address);
195   - pgprot_val(prot2) &= ~_PAGE_NX;
196   - err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC);
  195 + /* Make sure the kernel mappings stay executable */
  196 + prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
  197 + err = __change_page_attr(addr2, pfn, prot2,
  198 + PAGE_KERNEL_EXEC);
197 199 }
198 200 }
199 201 up_write(&init_mm.mmap_sem);
include/asm-x86_64/pgtable.h
... ... @@ -265,7 +265,7 @@
265 265 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
266 266 static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
267 267 static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
268   -static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
  268 +static inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_NX); }
269 269 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
270 270 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
271 271 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
... ... @@ -278,7 +278,7 @@
278 278 static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
279 279 static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
280 280 static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
281   -static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
  281 +static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX)); return pte; }
282 282 static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
283 283 static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
284 284 static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }