linux/arch/powerpc/lib
Michael Ellerman 49b39ec248 powerpc/64s: Fix entry flush patching w/strict RWX & hash
The entry flush mitigation can be enabled/disabled at runtime. When this
happens it results in the kernel patching its own instructions to
enable/disable the mitigation sequence.

With strict kernel RWX enabled instruction patching happens via a
secondary mapping of the kernel text, so that we don't have to make the
primary mapping writable. With the hash MMU this leads to a hash fault,
which causes us to execute the exception entry which contains the entry
flush mitigation.

This means we end up executing the entry flush in a semi-patched state,
ie. after we have patched the first instruction but before we patch the
second or third instruction of the sequence.

On machines with updated firmware the entry flush is a series of special
nops, and it's safe to to execute in a semi-patched state.

However when using the fallback flush the sequence is mflr/branch/mtlr,
and so it's not safe to execute if we have patched out the mflr but not
the other two instructions. Doing so leads to us corrputing LR, leading
to an oops, for example:

  # echo 0 > /sys/kernel/debug/powerpc/entry_flush
  kernel tried to execute exec-protected page (c000000002971000) - exploit attempt? (uid: 0)
  BUG: Unable to handle kernel instruction fetch
  Faulting instruction address: 0xc000000002971000
  Oops: Kernel access of bad area, sig: 11 [#1]
  LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries
  CPU: 0 PID: 2215 Comm: bash Not tainted 5.13.0-rc1-00010-gda3bb206c9ce #1
  NIP:  c000000002971000 LR: c000000002971000 CTR: c000000000120c40
  REGS: c000000013243840 TRAP: 0400   Not tainted  (5.13.0-rc1-00010-gda3bb206c9ce)
  MSR:  8000000010009033 <SF,EE,ME,IR,DR,RI,LE>  CR: 48428482  XER: 00000000
  ...
  NIP  0xc000000002971000
  LR   0xc000000002971000
  Call Trace:
    do_patch_instruction+0xc4/0x340 (unreliable)
    do_entry_flush_fixups+0x100/0x3b0
    entry_flush_set+0x50/0xe0
    simple_attr_write+0x160/0x1a0
    full_proxy_write+0x8c/0x110
    vfs_write+0xf0/0x340
    ksys_write+0x84/0x140
    system_call_exception+0x164/0x2d0
    system_call_common+0xec/0x278

The simplest fix is to change the order in which we patch the
instructions, so that the sequence is always safe to execute. For the
non-fallback flushes it doesn't matter what order we patch in.

Fixes: bd573a8131 ("powerpc/mm/64s: Allow STRICT_KERNEL_RWX again")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210513140800.1391706-1-mpe@ellerman.id.au
2021-05-14 17:27:36 +10:00
..
alloc.c treewide: add checks for the return value of memblock_alloc*() 2019-03-12 10:04:02 -07:00
checksum_32.S powerpc32: don't adjust unmoved stack pointer in csum_partial_copy_generic() epilogue 2020-10-14 16:04:13 -07:00
checksum_64.S ppc: propagate the calling conventions change down to csum_partial_copy_generic() 2020-08-20 15:45:22 -04:00
checksum_wrappers.c powerpc/net: Switch csum_and_copy_{to/from}_user to user_access block 2021-03-26 23:19:43 +11:00
code-patching.c powerpc/inst: ppc_inst_as_u64() becomes ppc_inst_as_ulong() 2021-04-21 22:52:32 +10:00
copy_32.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
copy_mc_64.S x86, powerpc: Rename memcpy_mcsafe() to copy_mc_to_{user, kernel}() 2020-10-06 11:18:04 +02:00
copypage_64.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
copypage_power7.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
copyuser_64.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
copyuser_power7.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
crtsavres.S powerpc/64: Do not create new section for save/restore functions 2017-05-30 14:59:51 +10:00
div64.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
error-inject.c powerpc: Add support for function error injection 2018-10-20 13:26:43 +11:00
feature-fixups-test.S powerpc: Test prefixed instructions in feature fixups 2020-05-19 00:11:02 +10:00
feature-fixups.c powerpc/64s: Fix entry flush patching w/strict RWX & hash 2021-05-14 17:27:36 +10:00
hweight_64.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
ldstfp.S powerpc updates for 5.3 2019-07-13 16:08:36 -07:00
locks.c powerpc/pseries: Move some PAPR paravirt functions to their own file 2020-07-26 23:34:26 +10:00
Makefile powerpc/32: Fix boot failure with CONFIG_STACKPROTECTOR 2021-05-04 22:28:05 +10:00
mem_64.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
memcmp_32.S powerpc/lib: optimise PPC32 memcmp 2018-06-04 00:39:21 +10:00
memcmp_64.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
memcpy_64.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
memcpy_power7.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
pmem.c powerpc/pmem: Include pmem prototypes 2021-01-30 11:39:28 +11:00
quad.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
rheap.c treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
sstep.c powerpc: remove partial register save logic 2021-04-14 23:04:44 +10:00
string_32.S powerpc: Fix __clear_user() with KUAP enabled 2019-12-16 23:19:44 +11:00
string_64.S powerpc: Fix __clear_user() with KUAP enabled 2019-12-16 23:19:44 +11:00
string.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
strlen_32.S powerpc/lib: Implement strlen() in assembly for PPC32 2018-08-07 21:49:30 +10:00
test_code-patching.S powerpc: Test prefixed code patching 2020-05-19 00:11:02 +10:00
test_emulate_step_exec_instr.S powerpc/sstep: Add tests for Prefixed Add Immediate 2020-07-23 17:25:21 +10:00
test_emulate_step.c powerpc/sstep: Add testcases for VSX vector paired load/store instructions 2020-12-11 00:09:10 +11:00
vmx-helper.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
xor_vmx_glue.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
xor_vmx.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
xor_vmx.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00