mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 05:02:31 +00:00
powerpc: Handle error in mark_rodata_ro() and mark_initmem_nx()
mark_rodata_ro() and mark_initmem_nx() use functions that can fail like set_memory_nx() and set_memory_ro(), leading to a not protected kernel. In case of failure, panic. Link: https://github.com/KSPP/linux/issues/7 Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://msgid.link/b16329611deb89e1af505d43f0e2a91310584d26.1710587887.git.christophe.leroy@csgroup.eu
This commit is contained in:
parent
66a27abac3
commit
78cb0945f7
@ -193,7 +193,7 @@ static bool is_module_segment(unsigned long addr)
|
||||
return true;
|
||||
}
|
||||
|
||||
void mmu_mark_initmem_nx(void)
|
||||
int mmu_mark_initmem_nx(void)
|
||||
{
|
||||
int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
|
||||
int i;
|
||||
@ -230,9 +230,10 @@ void mmu_mark_initmem_nx(void)
|
||||
|
||||
mtsr(mfsr(i << 28) | 0x10000000, i << 28);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mmu_mark_rodata_ro(void)
|
||||
int mmu_mark_rodata_ro(void)
|
||||
{
|
||||
int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
|
||||
int i;
|
||||
@ -245,6 +246,8 @@ void mmu_mark_rodata_ro(void)
|
||||
}
|
||||
|
||||
update_bats();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -160,11 +160,11 @@ static inline unsigned long p_block_mapped(phys_addr_t pa) { return 0; }
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC_E500)
|
||||
void mmu_mark_initmem_nx(void);
|
||||
void mmu_mark_rodata_ro(void);
|
||||
int mmu_mark_initmem_nx(void);
|
||||
int mmu_mark_rodata_ro(void);
|
||||
#else
|
||||
static inline void mmu_mark_initmem_nx(void) { }
|
||||
static inline void mmu_mark_rodata_ro(void) { }
|
||||
static inline int mmu_mark_initmem_nx(void) { return 0; }
|
||||
static inline int mmu_mark_rodata_ro(void) { return 0; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
|
@ -119,23 +119,26 @@ void __init mmu_mapin_immr(void)
|
||||
PAGE_KERNEL_NCG, MMU_PAGE_512K, true);
|
||||
}
|
||||
|
||||
static void mmu_mapin_ram_chunk(unsigned long offset, unsigned long top,
|
||||
pgprot_t prot, bool new)
|
||||
static int mmu_mapin_ram_chunk(unsigned long offset, unsigned long top,
|
||||
pgprot_t prot, bool new)
|
||||
{
|
||||
unsigned long v = PAGE_OFFSET + offset;
|
||||
unsigned long p = offset;
|
||||
int err = 0;
|
||||
|
||||
WARN_ON(!IS_ALIGNED(offset, SZ_512K) || !IS_ALIGNED(top, SZ_512K));
|
||||
|
||||
for (; p < ALIGN(p, SZ_8M) && p < top; p += SZ_512K, v += SZ_512K)
|
||||
__early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
|
||||
for (; p < ALIGN_DOWN(top, SZ_8M) && p < top; p += SZ_8M, v += SZ_8M)
|
||||
__early_map_kernel_hugepage(v, p, prot, MMU_PAGE_8M, new);
|
||||
for (; p < ALIGN_DOWN(top, SZ_512K) && p < top; p += SZ_512K, v += SZ_512K)
|
||||
__early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
|
||||
for (; p < ALIGN(p, SZ_8M) && p < top && !err; p += SZ_512K, v += SZ_512K)
|
||||
err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
|
||||
for (; p < ALIGN_DOWN(top, SZ_8M) && p < top && !err; p += SZ_8M, v += SZ_8M)
|
||||
err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_8M, new);
|
||||
for (; p < ALIGN_DOWN(top, SZ_512K) && p < top && !err; p += SZ_512K, v += SZ_512K)
|
||||
err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
|
||||
|
||||
if (!new)
|
||||
flush_tlb_kernel_range(PAGE_OFFSET + v, PAGE_OFFSET + top);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
|
||||
@ -166,27 +169,33 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
|
||||
return top;
|
||||
}
|
||||
|
||||
void mmu_mark_initmem_nx(void)
|
||||
int mmu_mark_initmem_nx(void)
|
||||
{
|
||||
unsigned long etext8 = ALIGN(__pa(_etext), SZ_8M);
|
||||
unsigned long sinittext = __pa(_sinittext);
|
||||
unsigned long boundary = strict_kernel_rwx_enabled() ? sinittext : etext8;
|
||||
unsigned long einittext8 = ALIGN(__pa(_einittext), SZ_8M);
|
||||
int err = 0;
|
||||
|
||||
if (!debug_pagealloc_enabled_or_kfence())
|
||||
mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL, false);
|
||||
err = mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL, false);
|
||||
|
||||
mmu_pin_tlb(block_mapped_ram, false);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
void mmu_mark_rodata_ro(void)
|
||||
int mmu_mark_rodata_ro(void)
|
||||
{
|
||||
unsigned long sinittext = __pa(_sinittext);
|
||||
int err;
|
||||
|
||||
mmu_mapin_ram_chunk(0, sinittext, PAGE_KERNEL_ROX, false);
|
||||
err = mmu_mapin_ram_chunk(0, sinittext, PAGE_KERNEL_ROX, false);
|
||||
if (IS_ENABLED(CONFIG_PIN_TLB_DATA))
|
||||
mmu_pin_tlb(block_mapped_ram, true);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -285,19 +285,23 @@ void __init adjust_total_lowmem(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
void mmu_mark_rodata_ro(void)
|
||||
int mmu_mark_rodata_ro(void)
|
||||
{
|
||||
unsigned long remapped;
|
||||
|
||||
remapped = map_mem_in_cams(__max_low_memory, CONFIG_LOWMEM_CAM_NUM, false, false);
|
||||
|
||||
WARN_ON(__max_low_memory != remapped);
|
||||
if (WARN_ON(__max_low_memory != remapped))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void mmu_mark_initmem_nx(void)
|
||||
int mmu_mark_initmem_nx(void)
|
||||
{
|
||||
/* Everything is done in mmu_mark_rodata_ro() */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setup_initial_memory_limit(phys_addr_t first_memblock_base,
|
||||
|
@ -130,31 +130,41 @@ void __init mapin_ram(void)
|
||||
}
|
||||
}
|
||||
|
||||
void mark_initmem_nx(void)
|
||||
static int __mark_initmem_nx(void)
|
||||
{
|
||||
unsigned long numpages = PFN_UP((unsigned long)_einittext) -
|
||||
PFN_DOWN((unsigned long)_sinittext);
|
||||
int err;
|
||||
|
||||
mmu_mark_initmem_nx();
|
||||
err = mmu_mark_initmem_nx();
|
||||
|
||||
if (!v_block_mapped((unsigned long)_sinittext)) {
|
||||
set_memory_nx((unsigned long)_sinittext, numpages);
|
||||
set_memory_rw((unsigned long)_sinittext, numpages);
|
||||
err = set_memory_nx((unsigned long)_sinittext, numpages);
|
||||
if (err)
|
||||
return err;
|
||||
err = set_memory_rw((unsigned long)_sinittext, numpages);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void mark_initmem_nx(void)
|
||||
{
|
||||
int err = __mark_initmem_nx();
|
||||
|
||||
if (err)
|
||||
panic("%s() failed, err = %d\n", __func__, err);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
void mark_rodata_ro(void)
|
||||
static int __mark_rodata_ro(void)
|
||||
{
|
||||
unsigned long numpages;
|
||||
|
||||
if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX) && mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||
pr_warn("This platform has HASH MMU, STRICT_MODULE_RWX won't work\n");
|
||||
|
||||
if (v_block_mapped((unsigned long)_stext + 1)) {
|
||||
mmu_mark_rodata_ro();
|
||||
return;
|
||||
}
|
||||
if (v_block_mapped((unsigned long)_stext + 1))
|
||||
return mmu_mark_rodata_ro();
|
||||
|
||||
/*
|
||||
* mark text and rodata as read only. __end_rodata is set by
|
||||
@ -164,6 +174,14 @@ void mark_rodata_ro(void)
|
||||
numpages = PFN_UP((unsigned long)__end_rodata) -
|
||||
PFN_DOWN((unsigned long)_stext);
|
||||
|
||||
set_memory_ro((unsigned long)_stext, numpages);
|
||||
return set_memory_ro((unsigned long)_stext, numpages);
|
||||
}
|
||||
|
||||
void mark_rodata_ro(void)
|
||||
{
|
||||
int err = __mark_rodata_ro();
|
||||
|
||||
if (err)
|
||||
panic("%s() failed, err = %d\n", __func__, err);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user