aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/mm/pageattr.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index cbe8e9223bee..00f6f341e291 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -24,22 +24,49 @@ void clflush_cache_range(void *addr, int size)
24#include <asm/pgalloc.h> 24#include <asm/pgalloc.h>
25 25
26/* 26/*
27 * We allow the BIOS range to be executable: 27 * We must allow the BIOS range to be executable:
28 */ 28 */
29#define BIOS_BEGIN 0x000a0000 29#define BIOS_BEGIN 0x000a0000
30#define BIOS_END 0x00100000 30#define BIOS_END 0x00100000
31 31
32static inline pgprot_t check_exec(pgprot_t prot, unsigned long address) 32static inline int
33within(unsigned long addr, unsigned long start, unsigned long end)
33{ 34{
34 if (__pa(address) >= BIOS_BEGIN && __pa(address) < BIOS_END) 35 return addr >= start && addr < end;
35 pgprot_val(prot) &= ~_PAGE_NX; 36}
37
38/*
39 * Certain areas of memory on x86 require very specific protection flags,
40 * for example the BIOS area or kernel text. Callers don't always get this
41 * right (again, ioremap() on BIOS memory is not uncommon) so this function
42 * checks and fixes these known static required protection bits.
43 */
44static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
45{
46 pgprot_t forbidden = __pgprot(0);
47
36 /* 48 /*
37 * Better fail early if someone sets the kernel text to NX. 49 * The BIOS area between 640k and 1Mb needs to be executable for
38 * Does not cover __inittext 50 * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support.
39 */ 51 */
40 BUG_ON(address >= (unsigned long)&_text && 52 if (within(__pa(address), BIOS_BEGIN, BIOS_END))
41 address < (unsigned long)&_etext && 53 pgprot_val(forbidden) |= _PAGE_NX;
42 (pgprot_val(prot) & _PAGE_NX)); 54
55 /*
56 * The kernel text needs to be executable for obvious reasons
57 * Does not cover __inittext since that is gone later on
58 */
59 if (within(address, (unsigned long)_text, (unsigned long)_etext))
60 pgprot_val(forbidden) |= _PAGE_NX;
61
62#ifdef CONFIG_DEBUG_RODATA
63 /* The .rodata section needs to be read-only */
64 if (within(address, (unsigned long)__start_rodata,
65 (unsigned long)__end_rodata))
66 pgprot_val(forbidden) |= _PAGE_RW;
67#endif
68
69 prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
43 70
44 return prot; 71 return prot;
45} 72}
@@ -169,7 +196,7 @@ repeat:
169 BUG_ON(PageLRU(kpte_page)); 196 BUG_ON(PageLRU(kpte_page));
170 BUG_ON(PageCompound(kpte_page)); 197 BUG_ON(PageCompound(kpte_page));
171 198
172 prot = check_exec(prot, address); 199 prot = static_protections(prot, address);
173 200
174 if (level == PG_LEVEL_4K) { 201 if (level == PG_LEVEL_4K) {
175 set_pte_atomic(kpte, pfn_pte(pfn, canon_pgprot(prot))); 202 set_pte_atomic(kpte, pfn_pte(pfn, canon_pgprot(prot)));