Skip to content

Commit 00ff1ea

Browse files
npigginmpe
authored andcommitted
powerpc: Fix reschedule bug in KUAP-unlocked user copy
schedule must not be explicitly called while KUAP is unlocked, because the AMR register will not be saved across the context switch on 64s (preemption is allowed because that is driven by interrupts which do save the AMR). exit_vmx_usercopy() runs inside an unlocked user access region, and it calls preempt_enable() which will call schedule() if need_resched() was set while non-preemptible. This can cause tasks to run unprotected when the should not, and can cause the user copy to be improperly blocked when scheduling back to it. Fix this by avoiding the explicit resched for preempt kernels by generating an interrupt to reschedule the context if need_resched() got set. Reported-by: Samuel Holland <[email protected]> Signed-off-by: Nicholas Piggin <[email protected]> Tested-by: Guenter Roeck <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 2b2095f commit 00ff1ea

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

arch/powerpc/lib/vmx-helper.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,17 @@ int exit_vmx_usercopy(void)
3636
{
3737
disable_kernel_altivec();
3838
pagefault_enable();
39-
preempt_enable();
39+
preempt_enable_no_resched();
40+
/*
41+
* Must never explicitly call schedule (including preempt_enable())
42+
* while in a kuap-unlocked user copy, because the AMR register will
43+
* not be saved and restored across context switch. However preempt
44+
* kernels need to be preempted as soon as possible if need_resched is
45+
* set and we are preemptible. The hack here is to schedule a
46+
* decrementer to fire here and reschedule for us if necessary.
47+
*/
48+
if (IS_ENABLED(CONFIG_PREEMPT) && need_resched())
49+
set_dec(1);
4050
return 0;
4151
}
4252

0 commit comments

Comments
 (0)