Commit 029d9252 authored by Michael Ellerman's avatar Michael Ellerman

powerpc/mm: Mark __init memory no-execute when STRICT_KERNEL_RWX=y

Currently even with STRICT_KERNEL_RWX we leave the __init text marked
executable after init, which is bad.

Add a hook to mark it NX (no-execute) before we free it, and implement
it for radix and hash.

Note that we use __init_end as the end address, not _einittext,
because overlaps_kernel_text() uses __init_end, because there are
additional executable sections other than .init.text between
__init_begin and __init_end.

Tested on radix and hash with:

  0:mon> p $__init_begin
  *** 400 exception occurred

Fixes: 1e0fc9d1 ("powerpc/Kconfig: Enable STRICT_KERNEL_RWX for some configs")
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent fa7f9189
...@@ -91,6 +91,7 @@ static inline int hash__pgd_bad(pgd_t pgd) ...@@ -91,6 +91,7 @@ static inline int hash__pgd_bad(pgd_t pgd)
} }
#ifdef CONFIG_STRICT_KERNEL_RWX #ifdef CONFIG_STRICT_KERNEL_RWX
extern void hash__mark_rodata_ro(void); extern void hash__mark_rodata_ro(void);
extern void hash__mark_initmem_nx(void);
#endif #endif
extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr, extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
......
...@@ -1192,5 +1192,6 @@ static inline const int pud_pfn(pud_t pud) ...@@ -1192,5 +1192,6 @@ static inline const int pud_pfn(pud_t pud)
BUILD_BUG(); BUILD_BUG();
return 0; return 0;
} }
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */ #endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */
...@@ -118,6 +118,7 @@ ...@@ -118,6 +118,7 @@
#ifdef CONFIG_STRICT_KERNEL_RWX #ifdef CONFIG_STRICT_KERNEL_RWX
extern void radix__mark_rodata_ro(void); extern void radix__mark_rodata_ro(void);
extern void radix__mark_initmem_nx(void);
#endif #endif
static inline unsigned long __radix_pte_update(pte_t *ptep, unsigned long clr, static inline unsigned long __radix_pte_update(pte_t *ptep, unsigned long clr,
......
...@@ -80,6 +80,13 @@ unsigned long vmalloc_to_phys(void *vmalloc_addr); ...@@ -80,6 +80,13 @@ unsigned long vmalloc_to_phys(void *vmalloc_addr);
void pgtable_cache_add(unsigned shift, void (*ctor)(void *)); void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
void pgtable_cache_init(void); void pgtable_cache_init(void);
#ifdef CONFIG_STRICT_KERNEL_RWX
void mark_initmem_nx(void);
#else
static inline void mark_initmem_nx(void) { }
#endif
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_PGTABLE_H */ #endif /* _ASM_POWERPC_PGTABLE_H */
...@@ -402,6 +402,7 @@ void __init mem_init(void) ...@@ -402,6 +402,7 @@ void __init mem_init(void)
void free_initmem(void) void free_initmem(void)
{ {
ppc_md.progress = ppc_printk_progress; ppc_md.progress = ppc_printk_progress;
mark_initmem_nx();
free_initmem_default(POISON_FREE_INITMEM); free_initmem_default(POISON_FREE_INITMEM);
} }
......
...@@ -460,4 +460,16 @@ void hash__mark_rodata_ro(void) ...@@ -460,4 +460,16 @@ void hash__mark_rodata_ro(void)
WARN_ON(!hash__change_memory_range(start, end, PP_RXXX)); WARN_ON(!hash__change_memory_range(start, end, PP_RXXX));
} }
void hash__mark_initmem_nx(void)
{
unsigned long start, end, pp;
start = (unsigned long)__init_begin;
end = (unsigned long)__init_end;
pp = htab_convert_pte_flags(pgprot_val(PAGE_KERNEL));
WARN_ON(!hash__change_memory_range(start, end, pp));
}
#endif #endif
...@@ -162,6 +162,14 @@ void radix__mark_rodata_ro(void) ...@@ -162,6 +162,14 @@ void radix__mark_rodata_ro(void)
radix__change_memory_range(start, end, _PAGE_WRITE); radix__change_memory_range(start, end, _PAGE_WRITE);
} }
void radix__mark_initmem_nx(void)
{
unsigned long start = (unsigned long)__init_begin;
unsigned long end = (unsigned long)__init_end;
radix__change_memory_range(start, end, _PAGE_EXEC);
}
#endif /* CONFIG_STRICT_KERNEL_RWX */ #endif /* CONFIG_STRICT_KERNEL_RWX */
static inline void __meminit print_mapping(unsigned long start, static inline void __meminit print_mapping(unsigned long start,
......
...@@ -505,4 +505,12 @@ void mark_rodata_ro(void) ...@@ -505,4 +505,12 @@ void mark_rodata_ro(void)
else else
hash__mark_rodata_ro(); hash__mark_rodata_ro();
} }
void mark_initmem_nx(void)
{
if (radix_enabled())
radix__mark_initmem_nx();
else
hash__mark_initmem_nx();
}
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment