linux/arch/powerpc/mm
Michael Ellerman 18bac7de24 powerpc/64s/radix: Fix crash with unaligned relocated kernel
commit 98d0219e04 upstream.

If a relocatable kernel is loaded at an address that is not 2MB aligned
and told not to relocate to zero, the kernel can crash due to
mark_rodata_ro() incorrectly changing some read-write data to read-only.

Scenarios where the misalignment can occur are when the kernel is
loaded by kdump or using the RELOCATABLE_TEST config option.

Example crash with the kernel loaded at 5MB:

  Run /sbin/init as init process
  BUG: Unable to handle kernel data access on write at 0xc000000000452000
  Faulting instruction address: 0xc0000000005b6730
  Oops: Kernel access of bad area, sig: 11 [#1]
  LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries
  CPU: 1 PID: 1 Comm: init Not tainted 6.2.0-rc1-00011-g349188be4841 #166
  Hardware name: IBM pSeries (emulated by qemu) POWER9 (raw) 0x4e1202 0xf000005 of:SLOF,git-5b4c5a hv:linux,kvm pSeries
  NIP:  c0000000005b6730 LR: c000000000ae9ab8 CTR: 0000000000000380
  REGS: c000000004503250 TRAP: 0300   Not tainted  (6.2.0-rc1-00011-g349188be4841)
  MSR:  8000000000009033 <SF,EE,ME,IR,DR,RI,LE>  CR: 44288480  XER: 00000000
  CFAR: c0000000005b66ec DAR: c000000000452000 DSISR: 0a000000 IRQMASK: 0
  ...
  NIP memset+0x68/0x104
  LR  zero_user_segments.constprop.0+0xa8/0xf0
  Call Trace:
    ext4_mpage_readpages+0x7f8/0x830
    ext4_readahead+0x48/0x60
    read_pages+0xb8/0x380
    page_cache_ra_unbounded+0x19c/0x250
    filemap_fault+0x58c/0xae0
    __do_fault+0x60/0x100
    __handle_mm_fault+0x1230/0x1a40
    handle_mm_fault+0x120/0x300
    ___do_page_fault+0x20c/0xa80
    do_page_fault+0x30/0xc0
    data_access_common_virt+0x210/0x220

This happens because mark_rodata_ro() tries to change permissions on the
range _stext..__end_rodata, but _stext sits in the middle of the 2MB
page from 4MB to 6MB:

  radix-mmu: Mapped 0x0000000000000000-0x0000000000200000 with 2.00 MiB pages (exec)
  radix-mmu: Mapped 0x0000000000200000-0x0000000000400000 with 2.00 MiB pages
  radix-mmu: Mapped 0x0000000000400000-0x0000000002400000 with 2.00 MiB pages (exec)

The logic that changes the permissions assumes the linear mapping was
split correctly at boot, so it marks the entire 2MB page read-only. That
leads to the write fault above.

To fix it, the boot time mapping logic needs to consider that if the
kernel is running at a non-zero address then _stext is a boundary where
it must split the mapping.

That leads to the mapping being split correctly, allowing the rodata
permission change to take happen correctly, with no spillover:

  radix-mmu: Mapped 0x0000000000000000-0x0000000000200000 with 2.00 MiB pages (exec)
  radix-mmu: Mapped 0x0000000000200000-0x0000000000400000 with 2.00 MiB pages
  radix-mmu: Mapped 0x0000000000400000-0x0000000000500000 with 64.0 KiB pages
  radix-mmu: Mapped 0x0000000000500000-0x0000000000600000 with 64.0 KiB pages (exec)
  radix-mmu: Mapped 0x0000000000600000-0x0000000002400000 with 2.00 MiB pages (exec)

If the kernel is loaded at a 2MB aligned address, the mapping continues
to use 2MB pages as before:

  radix-mmu: Mapped 0x0000000000000000-0x0000000000200000 with 2.00 MiB pages (exec)
  radix-mmu: Mapped 0x0000000000200000-0x0000000000400000 with 2.00 MiB pages
  radix-mmu: Mapped 0x0000000000400000-0x0000000002c00000 with 2.00 MiB pages (exec)
  radix-mmu: Mapped 0x0000000002c00000-0x0000000100000000 with 2.00 MiB pages

Fixes: c55d7b5e64 ("powerpc: Remove STRICT_KERNEL_RWX incompatibility with RELOCATABLE")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20230110124753.1325426-1-mpe@ellerman.id.au
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2023-02-09 11:28:26 +01:00
..
book3s32 - Yu Zhao's Multi-Gen LRU patches are here. They've been under test in 2022-10-10 17:53:04 -07:00
book3s64 powerpc/64s/radix: Fix crash with unaligned relocated kernel 2023-02-09 11:28:26 +01:00
kasan powerpc/32s: Fix boot failure with KASAN + SMP + JUMP_LABEL_FEATURE_CHECK_DEBUG 2022-07-27 21:36:05 +10:00
nohash powerpc/64e: provide an addressing macro for use with TOC in alternate register 2022-09-28 19:22:12 +10:00
ptdump powerpc: Remove CONFIG_PPC_BOOK3E_MMU 2022-09-26 23:00:14 +10:00
cacheflush.c powerpc: Fix all occurences of "the the" 2022-05-22 15:59:43 +10:00
copro_fault.c mm: avoid unnecessary page fault retires on shared memory types 2022-06-16 19:48:27 -07:00
dma-noncoherent.c dma-mapping: merge <linux/dma-noncoherent.h> into <linux/dma-map-ops.h> 2020-10-06 07:07:06 +02:00
drmem.c powerpc: Add missing headers 2022-05-08 22:15:40 +10:00
fault.c powerpc: Ignore DSI error caused by the copy/paste instruction 2022-09-28 22:52:32 +10:00
hugetlbpage.c powerpc/mm: Fix UBSAN warning reported on hugetlb 2022-09-30 18:35:52 +10:00
init-common.c powerpc/kuep: Remove 'nosmep' boot time parameter except for book3s/64 2021-12-09 22:41:18 +11:00
init_32.c powerpc: Remove CONFIG_FSL_BOOKE 2022-09-26 22:47:37 +10:00
init_64.c Merge branch 'topic/ppc-kvm' into next 2022-05-19 23:10:42 +10:00
ioremap.c powerpc: make memremap_compat_align 64s-only 2021-12-02 22:57:24 +11:00
ioremap_32.c powerpc/mm: Leave a gap between early allocated IO areas 2021-06-25 00:07:10 +10:00
ioremap_64.c powerpc/mm: Leave a gap between early allocated IO areas 2021-06-25 00:07:10 +10:00
maccess.c powerpc/inst: Optimise copy_inst_from_kernel_nofault() 2021-12-09 22:41:21 +11:00
Makefile powerpc/mm: Convert to default topdown mmap layout 2022-05-05 22:11:58 +10:00
mem.c powerpc: Remove CONFIG_PPC_FSL_BOOK3E 2022-09-26 23:00:13 +10:00
mmu_context.c powerpc/mm: Switch obsolete dssall to .long 2021-12-23 22:35:13 +11:00
mmu_decl.h powerpc: Remove CONFIG_PPC_FSL_BOOK3E 2022-09-26 23:00:13 +10:00
numa.c powerpc/mm: Always update max/min_low_pfn in mem_topology_setup() 2022-09-30 18:35:52 +10:00
pageattr.c powerpc: align address to page boundary in change_page_attr() 2022-05-08 22:15:41 +10:00
pgtable-frag.c powerpc: fix typos in comments 2022-05-05 22:12:44 +10:00
pgtable.c powerpc/mm: move protection_map[] inside the platform 2022-07-17 17:14:37 -07:00
pgtable_32.c powerpc: move __end_rodata to cover arch read-only sections 2022-09-26 20:58:16 +10:00
pgtable_64.c powerpc: Remove asm/prom.h from all files that don't need it 2022-05-08 22:15:04 +10:00