| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- From b5143e55b3bf018b3ad2598e677ceb5e155eba6f Mon Sep 17 00:00:00 2001
- From: Andy Lutomirski <[email protected]>
- Date: Sun, 17 Sep 2017 09:03:49 -0700
- Subject: [PATCH 044/242] x86/mm/64: Stop using CR3.PCID == 0 in ASID-aware
- code
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- CVE-2017-5754
- Putting the logical ASID into CR3's PCID bits directly means that we
- have two cases to consider separately: ASID == 0 and ASID != 0.
- This means that bugs that only hit in one of these cases trigger
- nondeterministically.
- There were some bugs like this in the past, and I think there's
- still one in current kernels. In particular, we have a number of
- ASID-unware code paths that save CR3, write some special value, and
- then restore CR3. This includes suspend/resume, hibernate, kexec,
- EFI, and maybe other things I've missed. This is currently
- dangerous: if ASID != 0, then this code sequence will leave garbage
- in the TLB tagged for ASID 0. We could potentially see corruption
- when switching back to ASID 0. In principle, an
- initialize_tlbstate_and_flush() call after these sequences would
- solve the problem, but EFI, at least, does not call this. (And it
- probably shouldn't -- initialize_tlbstate_and_flush() is rather
- expensive.)
- Signed-off-by: Andy Lutomirski <[email protected]>
- Cc: Borislav Petkov <[email protected]>
- Cc: Linus Torvalds <[email protected]>
- Cc: Peter Zijlstra <[email protected]>
- Cc: Thomas Gleixner <[email protected]>
- Link: http://lkml.kernel.org/r/cdc14bbe5d3c3ef2a562be09a6368ffe9bd947a6.1505663533.git.luto@kernel.org
- Signed-off-by: Ingo Molnar <[email protected]>
- (cherry picked from commit 52a2af400c1075219b3f0ce5c96fc961da44018a)
- Signed-off-by: Andy Whitcroft <[email protected]>
- Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
- (cherry picked from commit 15e474753e66e44da1365049f465427053a453ba)
- Signed-off-by: Fabian Grünbichler <[email protected]>
- ---
- arch/x86/include/asm/mmu_context.h | 21 +++++++++++++++++++--
- 1 file changed, 19 insertions(+), 2 deletions(-)
- diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
- index a999ba6b721f..c120b5db178a 100644
- --- a/arch/x86/include/asm/mmu_context.h
- +++ b/arch/x86/include/asm/mmu_context.h
- @@ -286,14 +286,31 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
- return __pkru_allows_pkey(vma_pkey(vma), write);
- }
-
- +/*
- + * If PCID is on, ASID-aware code paths put the ASID+1 into the PCID
- + * bits. This serves two purposes. It prevents a nasty situation in
- + * which PCID-unaware code saves CR3, loads some other value (with PCID
- + * == 0), and then restores CR3, thus corrupting the TLB for ASID 0 if
- + * the saved ASID was nonzero. It also means that any bugs involving
- + * loading a PCID-enabled CR3 with CR4.PCIDE off will trigger
- + * deterministically.
- + */
- +
- static inline unsigned long build_cr3(struct mm_struct *mm, u16 asid)
- {
- - return __sme_pa(mm->pgd) | asid;
- + if (static_cpu_has(X86_FEATURE_PCID)) {
- + VM_WARN_ON_ONCE(asid > 4094);
- + return __sme_pa(mm->pgd) | (asid + 1);
- + } else {
- + VM_WARN_ON_ONCE(asid != 0);
- + return __sme_pa(mm->pgd);
- + }
- }
-
- static inline unsigned long build_cr3_noflush(struct mm_struct *mm, u16 asid)
- {
- - return __sme_pa(mm->pgd) | asid | CR3_NOFLUSH;
- + VM_WARN_ON_ONCE(asid > 4094);
- + return __sme_pa(mm->pgd) | (asid + 1) | CR3_NOFLUSH;
- }
-
- /*
- --
- 2.14.2
|