[PATCH] powerpc/tm: Fix userspace r13 corruption

Michael Neuling mikey at neuling.org
Tue Sep 25 15:24:33 AEST 2018


On Mon, 2018-09-24 at 11:32 -0300, Breno Leitao wrote:
> Hi Mikey,
> 
> On 09/24/2018 04:27 AM, Michael Neuling wrote:
> > When we treclaim we store the userspace checkpointed r13 to a scratch
> > SPR and then later save the scratch SPR to the user thread struct.
> > 
> > Unfortunately, this doesn't work as accessing the user thread struct
> > can take an SLB fault and the SLB fault handler will write the same
> > scratch SPRG that now contains the userspace r13.
> > 
> > To fix this, we store r13 to the kernel stack (which can't fault)
> > before we access the user thread struct.
> > 
> > Found by running P8 guest + powervm + disable_1tb_segments + TM. Seen
> > as a random userspace segfault with r13 looking like a kernel address.
> > 
> > Signed-off-by: Michael Neuling <mikey at neuling.org>
> 
> Reviewed-by: Breno Leitao <leitao at debian.org>
> 
> I am wondering if the same problem could not happen with r1 as well, since r1
> is kept in the paca->tm_scratch after MSR[RI] is enabled, in a code similar
> to this:
> 
>         std     r1, PACATMSCRATCH(r13)
> 	..
>         li      r11, MSR_RI
> 	mtmsrd  r11, 1
> 	....
>         ld      r3, PACATMSCRATCH(r13)          /* user r1 */
>         std     r3, GPR1(r7)
> 
> There might be a corruption if the exception that is raised just after
> MSR[RI] is enabled somehow exits through 'fast_exception_return' (being
> called by most of the exception handlers as I understand) which will
> overwrite paca->tm_scratch with the upcoming MSR (aka SRR1) just before the
> SRR1, as:
> 
> 	ld      r3,_MSR(r1)
> 
> 	...
> 	std     r3, PACATMSCRATCH(r13) /* Stash returned-to MSR */
> 
> 
> It seems that slb_miss_common and instruction_access_slb does not go through
> this path, but handle_page_fault calls
> ret_from_except_lite->fast_exception_return, which might cause this
> 'possible' issue.

Yeah, good catch! I think we are ok but it's delicate. 

I'll store it in the kernel stack and avoid PACATMSCRATCH before I turn RI on.  

This look ok?

diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index 701b0f5b09..ff781b2852 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -178,6 +178,12 @@ _GLOBAL(tm_reclaim)
 
 	std	r11, GPR11(r1)			/* Temporary stash */
 
+	/* Move r1 to kernel stack in case PACATMSCRATCH is used once
+	 * we turn on RI
+	 */
+	ld	r11, PACATMSCRATCH(r13)
+	std	r11, GPR1(r1)
+
 	/* Store r13 away so we can free up the scratch SPR for the
 	 * SLB fault handler (needed once we start access the
 	 * thread_struct)
@@ -214,7 +220,7 @@ _GLOBAL(tm_reclaim)
 	SAVE_GPR(8, r7)				/* user r8 */
 	SAVE_GPR(9, r7)				/* user r9 */
 	SAVE_GPR(10, r7)			/* user r10 */
-	ld	r3, PACATMSCRATCH(r13)		/* user r1 */
+	ld	r3, GPR1(r1)			/* user r1 */
 	ld	r4, GPR7(r1)			/* user r7 */
 	ld	r5, GPR11(r1)			/* user r11 */
 	ld	r6, GPR12(r1)			/* user r12 */




More information about the Linuxppc-dev mailing list