powerpc/64/interrupt: Temporarily save PPR on stack to fix register corruption due to SLB miss
This is a minimal stable kernel fix for the problem solved by 4c2de74cc869 ("powerpc/64: Interrupts save PPR on stack rather than thread_struct"). Upstream kernels between 4.17-4.20 have this bug, so I propose this patch for 4.19 stable. Longer description from mpe: In commit f384796c ("powerpc/mm: Add support for handling > 512TB address in SLB miss") we added support for using multiple context ids per process. Previously accessing past the first context id was a fatal error for the process. With the new support it became non-fatal, and so the previous "bad_addr_slb" handler was changed to be the "large_addr_slb" handler. That handler uses the EXCEPTION_PROLOG_COMMON() macro, which in-turn calls the SAVE_PPR() macro. At the point where SAVE_PPR() is used, the r9-13 register values from the original user fault are saved in paca->exslb. It's not until later in EXCEPTION_PROLOG_COMMON_2() that they are saved from paca->exslb onto the kernel stack. The PPR is saved into current->thread.ppr, which is notably not on the kernel stack the way pt_regs are. This means we can take an SLB miss on current->thread.ppr. If that happens in the "large_addr_slb" case we will clobber the saved user r9-r13 in paca->exslb with kernel values. Later we will save those clobbered values into the pt_regs on the stack, and when we return to userspace those kernel values will be restored. Typically this appears as some sort of segfault in userspace, with an address that looks like a kernel address. In dmesg it can appear as: [19117.440331] some_program[1869625]: unhandled signal 11 at c00000000f6bda10 nip 00007fff780d559c lr 00007fff781ae56c code 30001 The upstream fix for this issue was to move PPR into pt_regs, on the kernel stack, avoiding the possibility of an SLB fault when saving it. However changing the size of pt_regs is an intrusive change, and has side effects in other parts of the kernel. A minimal fix is to temporarily save the PPR in an unused part of pt_regs, then save the user register values from paca->exslb into pt_regs, and then move the saved PPR into thread.ppr. Fixes: f384796c ("powerpc/mm: Add support for handling > 512TB address in SLB miss") Signed-off-by:Nicholas Piggin <npiggin@gmail.com> Signed-off-by:
Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20220316033235.903657-1-npiggin@gmail.com Signed-off-by:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Loading
Please register or sign in to comment