| From 2427eb2cf6448dc6d42e20c427b88a7c774a4e23 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 22 Jun 2021 15:30:36 +1000 |
| Subject: powerpc/64s: Fix copy-paste data exposure into newly created tasks |
| |
| From: Nicholas Piggin <npiggin@gmail.com> |
| |
| [ Upstream commit f35d2f249ef05b9671e7898f09ad89aa78f99122 ] |
| |
| 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: 07d2a628bc000 ("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 |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/powerpc/kernel/process.c | 48 +++++++++++++++++++++++------------ |
| 1 file changed, 32 insertions(+), 16 deletions(-) |
| |
| diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c |
| index 1a1d2657fe8d..3064694afea1 100644 |
| --- a/arch/powerpc/kernel/process.c |
| +++ b/arch/powerpc/kernel/process.c |
| @@ -1227,6 +1227,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 |
| @@ -1272,30 +1285,33 @@ struct task_struct *__switch_to(struct task_struct *prev, |
| |
| 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; |
| -- |
| 2.30.2 |
| |