powerpc/64s: Fix copy-paste data exposure into newly created tasks
copy-paste contains implicit "copy buffer" state that can contain
arbitrary user data (if the user process executes a copy instruction).
This could be snooped by another process if a context switch hits while
the state is live. So cp_abort is executed on context switch to clear
out possible sensitive data and prevent the leak.
cp_abort is done after the low level _switch(), which means it is never
reached by newly created tasks, so they could snoop on this buffer
between their first and second context switch.
Fix this by doing the cp_abort before calling _switch. Add some
comments which should make the issue harder to miss.
Fixes: 07d2a628bc
("powerpc/64s: Avoid cpabort in context switch when possible")
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210622053036.474678-1-npiggin@gmail.com
This commit is contained in:
parent
a27755d57e
commit
f35d2f249e
|
@ -1223,6 +1223,19 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
|||
__flush_tlb_pending(batch);
|
||||
batch->active = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On POWER9 the copy-paste buffer can only paste into
|
||||
* foreign real addresses, so unprivileged processes can not
|
||||
* see the data or use it in any way unless they have
|
||||
* foreign real mappings. If the new process has the foreign
|
||||
* real address mappings, we must issue a cp_abort to clear
|
||||
* any state and prevent snooping, corruption or a covert
|
||||
* channel. ISA v3.1 supports paste into local memory.
|
||||
*/
|
||||
if (new->mm && (cpu_has_feature(CPU_FTR_ARCH_31) ||
|
||||
atomic_read(&new->mm->context.vas_windows)))
|
||||
asm volatile(PPC_CP_ABORT);
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
||||
|
@ -1273,30 +1286,33 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
|||
#endif
|
||||
last = _switch(old_thread, new_thread);
|
||||
|
||||
/*
|
||||
* Nothing after _switch will be run for newly created tasks,
|
||||
* because they switch directly to ret_from_fork/ret_from_kernel_thread
|
||||
* etc. Code added here should have a comment explaining why that is
|
||||
* okay.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
/*
|
||||
* This applies to a process that was context switched while inside
|
||||
* arch_enter_lazy_mmu_mode(), to re-activate the batch that was
|
||||
* deactivated above, before _switch(). This will never be the case
|
||||
* for new tasks.
|
||||
*/
|
||||
if (current_thread_info()->local_flags & _TLF_LAZY_MMU) {
|
||||
current_thread_info()->local_flags &= ~_TLF_LAZY_MMU;
|
||||
batch = this_cpu_ptr(&ppc64_tlb_batch);
|
||||
batch->active = 1;
|
||||
}
|
||||
|
||||
if (current->thread.regs) {
|
||||
/*
|
||||
* Math facilities are masked out of the child MSR in copy_thread.
|
||||
* A new task does not need to restore_math because it will
|
||||
* demand fault them.
|
||||
*/
|
||||
if (current->thread.regs)
|
||||
restore_math(current->thread.regs);
|
||||
|
||||
/*
|
||||
* On POWER9 the copy-paste buffer can only paste into
|
||||
* foreign real addresses, so unprivileged processes can not
|
||||
* see the data or use it in any way unless they have
|
||||
* foreign real mappings. If the new process has the foreign
|
||||
* real address mappings, we must issue a cp_abort to clear
|
||||
* any state and prevent snooping, corruption or a covert
|
||||
* channel. ISA v3.1 supports paste into local memory.
|
||||
*/
|
||||
if (current->mm &&
|
||||
(cpu_has_feature(CPU_FTR_ARCH_31) ||
|
||||
atomic_read(¤t->mm->context.vas_windows)))
|
||||
asm volatile(PPC_CP_ABORT);
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
return last;
|
||||
|
|
Loading…
Reference in New Issue