• Michael Ellerman's avatar
    powerpc/64s: Fix entry flush patching w/strict RWX & hash · 49b39ec2
    Michael Ellerman authored
    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-gda3bb206 #1
      NIP:  c000000002971000 LR: c000000002971000 CTR: c000000000120c40
      REGS: c000000013243840 TRAP: 0400   Not tainted  (5.13.0-rc1-00010-gda3bb206)
      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: bd573a81 ("powerpc/mm/64s: Allow STRICT_KERNEL_RWX again")
    Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
    Link: https://lore.kernel.org/r/20210513140800.1391706-1-mpe@ellerman.id.au
    49b39ec2
feature-fixups.c 29.7 KB