powerpc/32: Fix vmap stack - Properly set r1 before activating MMU on syscall too
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Mon, 21 Dec 2020 06:18:03 +0000 (06:18 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 21 Dec 2020 11:24:00 +0000 (22:24 +1100)
We need r1 to be properly set before activating MMU, otherwise any new
exception taken while saving registers into the stack in syscall
prologs will use the user stack, which is wrong and will even lockup
or crash when KUAP is selected.

Do that by switching the meaning of r11 and r1 until we have saved r1
to the stack: copy r1 into r11 and setup the new stack pointer in r1.
To avoid complicating and impacting all generic and specific prolog
code (and more), copy back r1 into r11 once r11 is save onto
the stack.

We could get rid of copying r1 back and forth at the cost of rewriting
everything to use r1 instead of r11 all the way when CONFIG_VMAP_STACK
is set, but the effort is probably not worth it for now.

Fixes: da7bb43ab9da ("powerpc/32: Fix vmap stack - Properly set r1 before activating MMU")
Cc: stable@vger.kernel.org # v5.10+
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/a3d819d5c348cee9783a311d5d3f3ba9b48fd219.1608531452.git.christophe.leroy@csgroup.eu
arch/powerpc/kernel/head_32.h

index 541664d..a2f72c9 100644 (file)
 #ifdef CONFIG_VMAP_STACK
        mfspr   r11, SPRN_SRR0
        mtctr   r11
-#endif
        andi.   r11, r9, MSR_PR
-       lwz     r11,TASK_STACK-THREAD(r12)
+       mr      r11, r1
+       lwz     r1,TASK_STACK-THREAD(r12)
        beq-    99f
-       addi    r11, r11, THREAD_SIZE - INT_FRAME_SIZE
-#ifdef CONFIG_VMAP_STACK
+       addi    r1, r1, THREAD_SIZE - INT_FRAME_SIZE
        li      r10, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */
        mtmsr   r10
        isync
+       tovirt(r12, r12)
+       stw     r11,GPR1(r1)
+       stw     r11,0(r1)
+       mr      r11, r1
+#else
+       andi.   r11, r9, MSR_PR
+       lwz     r11,TASK_STACK-THREAD(r12)
+       beq-    99f
+       addi    r11, r11, THREAD_SIZE - INT_FRAME_SIZE
+       tophys(r11, r11)
+       stw     r1,GPR1(r11)
+       stw     r1,0(r11)
+       tovirt(r1, r11)         /* set new kernel sp */
 #endif
-       tovirt_vmstack r12, r12
-       tophys_novmstack r11, r11
        mflr    r10
        stw     r10, _LINK(r11)
 #ifdef CONFIG_VMAP_STACK
 #else
        mfspr   r10,SPRN_SRR0
 #endif
-       stw     r1,GPR1(r11)
-       stw     r1,0(r11)
-       tovirt_novmstack r1, r11        /* set new kernel sp */
        stw     r10,_NIP(r11)
        mfcr    r10
        rlwinm  r10,r10,0,4,2   /* Clear SO bit in CR */