mirror of https://gitee.com/openkylin/linux.git
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);
|
__flush_tlb_pending(batch);
|
||||||
batch->active = 0;
|
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 */
|
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
||||||
|
@ -1273,30 +1286,33 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
||||||
#endif
|
#endif
|
||||||
last = _switch(old_thread, new_thread);
|
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
|
#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) {
|
if (current_thread_info()->local_flags & _TLF_LAZY_MMU) {
|
||||||
current_thread_info()->local_flags &= ~_TLF_LAZY_MMU;
|
current_thread_info()->local_flags &= ~_TLF_LAZY_MMU;
|
||||||
batch = this_cpu_ptr(&ppc64_tlb_batch);
|
batch = this_cpu_ptr(&ppc64_tlb_batch);
|
||||||
batch->active = 1;
|
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);
|
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 */
|
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||||
|
|
||||||
return last;
|
return last;
|
||||||
|
|
Loading…
Reference in New Issue