diff options
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r-- | arch/powerpc/mm/mem.c | 1 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable-hash64.c | 44 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable-radix.c | 28 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable_64.c | 8 |
4 files changed, 63 insertions, 18 deletions
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 8541f18694a4..46b4e67d2372 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -402,6 +402,7 @@ void __init mem_init(void) | |||
402 | void free_initmem(void) | 402 | void free_initmem(void) |
403 | { | 403 | { |
404 | ppc_md.progress = ppc_printk_progress; | 404 | ppc_md.progress = ppc_printk_progress; |
405 | mark_initmem_nx(); | ||
405 | free_initmem_default(POISON_FREE_INITMEM); | 406 | free_initmem_default(POISON_FREE_INITMEM); |
406 | } | 407 | } |
407 | 408 | ||
diff --git a/arch/powerpc/mm/pgtable-hash64.c b/arch/powerpc/mm/pgtable-hash64.c index 188b4107584d..443a2c66a304 100644 --- a/arch/powerpc/mm/pgtable-hash64.c +++ b/arch/powerpc/mm/pgtable-hash64.c | |||
@@ -425,33 +425,51 @@ int hash__has_transparent_hugepage(void) | |||
425 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 425 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
426 | 426 | ||
427 | #ifdef CONFIG_STRICT_KERNEL_RWX | 427 | #ifdef CONFIG_STRICT_KERNEL_RWX |
428 | void hash__mark_rodata_ro(void) | 428 | static bool hash__change_memory_range(unsigned long start, unsigned long end, |
429 | unsigned long newpp) | ||
429 | { | 430 | { |
430 | unsigned long start = (unsigned long)_stext; | ||
431 | unsigned long end = (unsigned long)__init_begin; | ||
432 | unsigned long idx; | 431 | unsigned long idx; |
433 | unsigned int step, shift; | 432 | unsigned int step, shift; |
434 | unsigned long newpp = PP_RXXX; | ||
435 | 433 | ||
436 | shift = mmu_psize_defs[mmu_linear_psize].shift; | 434 | shift = mmu_psize_defs[mmu_linear_psize].shift; |
437 | step = 1 << shift; | 435 | step = 1 << shift; |
438 | 436 | ||
439 | start = ((start + step - 1) >> shift) << shift; | 437 | start = ALIGN_DOWN(start, step); |
440 | end = (end >> shift) << shift; | 438 | end = ALIGN(end, step); // aligns up |
441 | 439 | ||
442 | pr_devel("marking ro start %lx, end %lx, step %x\n", | 440 | if (start >= end) |
443 | start, end, step); | 441 | return false; |
444 | 442 | ||
445 | if (start == end) { | 443 | pr_debug("Changing page protection on range 0x%lx-0x%lx, to 0x%lx, step 0x%x\n", |
446 | pr_warn("could not set rodata ro, relocate the start" | 444 | start, end, newpp, step); |
447 | " of the kernel to a 0x%x boundary\n", step); | ||
448 | return; | ||
449 | } | ||
450 | 445 | ||
451 | for (idx = start; idx < end; idx += step) | 446 | for (idx = start; idx < end; idx += step) |
452 | /* Not sure if we can do much with the return value */ | 447 | /* Not sure if we can do much with the return value */ |
453 | mmu_hash_ops.hpte_updateboltedpp(newpp, idx, mmu_linear_psize, | 448 | mmu_hash_ops.hpte_updateboltedpp(newpp, idx, mmu_linear_psize, |
454 | mmu_kernel_ssize); | 449 | mmu_kernel_ssize); |
455 | 450 | ||
451 | return true; | ||
452 | } | ||
453 | |||
454 | void hash__mark_rodata_ro(void) | ||
455 | { | ||
456 | unsigned long start, end; | ||
457 | |||
458 | start = (unsigned long)_stext; | ||
459 | end = (unsigned long)__init_begin; | ||
460 | |||
461 | WARN_ON(!hash__change_memory_range(start, end, PP_RXXX)); | ||
462 | } | ||
463 | |||
464 | void hash__mark_initmem_nx(void) | ||
465 | { | ||
466 | unsigned long start, end, pp; | ||
467 | |||
468 | start = (unsigned long)__init_begin; | ||
469 | end = (unsigned long)__init_end; | ||
470 | |||
471 | pp = htab_convert_pte_flags(pgprot_val(PAGE_KERNEL)); | ||
472 | |||
473 | WARN_ON(!hash__change_memory_range(start, end, pp)); | ||
456 | } | 474 | } |
457 | #endif | 475 | #endif |
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index 8c13e4282308..5cc50d47ce3f 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c | |||
@@ -112,10 +112,9 @@ set_the_pte: | |||
112 | } | 112 | } |
113 | 113 | ||
114 | #ifdef CONFIG_STRICT_KERNEL_RWX | 114 | #ifdef CONFIG_STRICT_KERNEL_RWX |
115 | void radix__mark_rodata_ro(void) | 115 | void radix__change_memory_range(unsigned long start, unsigned long end, |
116 | unsigned long clear) | ||
116 | { | 117 | { |
117 | unsigned long start = (unsigned long)_stext; | ||
118 | unsigned long end = (unsigned long)__init_begin; | ||
119 | unsigned long idx; | 118 | unsigned long idx; |
120 | pgd_t *pgdp; | 119 | pgd_t *pgdp; |
121 | pud_t *pudp; | 120 | pud_t *pudp; |
@@ -125,7 +124,8 @@ void radix__mark_rodata_ro(void) | |||
125 | start = ALIGN_DOWN(start, PAGE_SIZE); | 124 | start = ALIGN_DOWN(start, PAGE_SIZE); |
126 | end = PAGE_ALIGN(end); // aligns up | 125 | end = PAGE_ALIGN(end); // aligns up |
127 | 126 | ||
128 | pr_devel("marking ro start %lx, end %lx\n", start, end); | 127 | pr_debug("Changing flags on range %lx-%lx removing 0x%lx\n", |
128 | start, end, clear); | ||
129 | 129 | ||
130 | for (idx = start; idx < end; idx += PAGE_SIZE) { | 130 | for (idx = start; idx < end; idx += PAGE_SIZE) { |
131 | pgdp = pgd_offset_k(idx); | 131 | pgdp = pgd_offset_k(idx); |
@@ -147,11 +147,29 @@ void radix__mark_rodata_ro(void) | |||
147 | if (!ptep) | 147 | if (!ptep) |
148 | continue; | 148 | continue; |
149 | update_the_pte: | 149 | update_the_pte: |
150 | radix__pte_update(&init_mm, idx, ptep, _PAGE_WRITE, 0, 0); | 150 | radix__pte_update(&init_mm, idx, ptep, clear, 0, 0); |
151 | } | 151 | } |
152 | 152 | ||
153 | radix__flush_tlb_kernel_range(start, end); | 153 | radix__flush_tlb_kernel_range(start, end); |
154 | } | 154 | } |
155 | |||
156 | void radix__mark_rodata_ro(void) | ||
157 | { | ||
158 | unsigned long start, end; | ||
159 | |||
160 | start = (unsigned long)_stext; | ||
161 | end = (unsigned long)__init_begin; | ||
162 | |||
163 | radix__change_memory_range(start, end, _PAGE_WRITE); | ||
164 | } | ||
165 | |||
166 | void radix__mark_initmem_nx(void) | ||
167 | { | ||
168 | unsigned long start = (unsigned long)__init_begin; | ||
169 | unsigned long end = (unsigned long)__init_end; | ||
170 | |||
171 | radix__change_memory_range(start, end, _PAGE_EXEC); | ||
172 | } | ||
155 | #endif /* CONFIG_STRICT_KERNEL_RWX */ | 173 | #endif /* CONFIG_STRICT_KERNEL_RWX */ |
156 | 174 | ||
157 | static inline void __meminit print_mapping(unsigned long start, | 175 | static inline void __meminit print_mapping(unsigned long start, |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 5c0b795d656c..0736e94c7615 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -505,4 +505,12 @@ void mark_rodata_ro(void) | |||
505 | else | 505 | else |
506 | hash__mark_rodata_ro(); | 506 | hash__mark_rodata_ro(); |
507 | } | 507 | } |
508 | |||
509 | void mark_initmem_nx(void) | ||
510 | { | ||
511 | if (radix_enabled()) | ||
512 | radix__mark_initmem_nx(); | ||
513 | else | ||
514 | hash__mark_initmem_nx(); | ||
515 | } | ||
508 | #endif | 516 | #endif |