diff options
author | Andi Kleen <ak@suse.de> | 2006-09-26 04:52:37 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:37 -0400 |
commit | df992848f5aa803fcacd2c5e7d67034bb89e3fa3 (patch) | |
tree | 649ee5888f71bdd4243599f73d9725118262d368 | |
parent | d3cf7f061521c78ad62e275eb6fbdc8f43fc75a7 (diff) |
[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>
-rw-r--r-- | arch/x86_64/mm/pageattr.c | 8 | ||||
-rw-r--r-- | include/asm-x86_64/pgtable.h | 4 |
2 files changed, 7 insertions, 5 deletions
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index 2685b1f3671c..01591b649f4e 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c | |||
@@ -190,10 +190,12 @@ int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot) | |||
190 | * lowmem */ | 190 | * lowmem */ |
191 | if (__pa(address) < KERNEL_TEXT_SIZE) { | 191 | if (__pa(address) < KERNEL_TEXT_SIZE) { |
192 | unsigned long addr2; | 192 | unsigned long addr2; |
193 | pgprot_t prot2 = prot; | 193 | pgprot_t prot2; |
194 | addr2 = __START_KERNEL_map + __pa(address); | 194 | addr2 = __START_KERNEL_map + __pa(address); |
195 | pgprot_val(prot2) &= ~_PAGE_NX; | 195 | /* Make sure the kernel mappings stay executable */ |
196 | err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC); | 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 | up_write(&init_mm.mmap_sem); | 201 | up_write(&init_mm.mmap_sem); |
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index d79e7441b513..f7614670c655 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h | |||
@@ -265,7 +265,7 @@ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) | |||
265 | #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT) | 265 | #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT) |
266 | static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; } | 266 | static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; } |
267 | static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } | 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 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } | 269 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } |
270 | static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } | 270 | static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } |
271 | static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } | 271 | static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } |
@@ -278,7 +278,7 @@ static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & | |||
278 | static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; } | 278 | static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; } |
279 | static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; } | 279 | static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; } |
280 | static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; } | 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 | static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } | 282 | static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } |
283 | static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } | 283 | static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } |
284 | static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } | 284 | static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } |