]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
KVM: PPC: Book3S HV: Flush link stack on guest exit to host kernel
authorMichael Ellerman <mpe@ellerman.id.au>
Thu, 28 Nov 2019 15:05:47 +0000 (10:05 -0500)
committerStefan Bader <stefan.bader@canonical.com>
Wed, 4 Dec 2019 09:29:26 +0000 (10:29 +0100)
BugLink: https://bugs.launchpad.net/bugs/1853142
commit af2e8c68b9c5403f77096969c516f742f5bb29e0 upstream.

On some systems that are vulnerable to Spectre v2, it is up to
software to flush the link stack (return address stack), in order to
protect against Spectre-RSB.

When exiting from a guest we do some house keeping and then
potentially exit to C code which is several stack frames deep in the
host kernel. We will then execute a series of returns without
preceeding calls, opening up the possiblity that the guest could have
poisoned the link stack, and direct speculative execution of the host
to a gadget of some sort.

To prevent this we add a flush of the link stack on exit from a guest.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Daniel Axtens <dja@axtens.net>
CVE-2019-18660
Signed-off-by: Benjamin M Romer <benjamin.romer@canonical.com>
Acked-by: Sultan Alsawaf <sultan.alsawaf@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
arch/powerpc/include/asm/asm-prototypes.h
arch/powerpc/kernel/security.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index aa58a7eb7eb2523b32572ba4b32dbbdc2747da83..baaafc9b9d887c993bdf75e5c640b116f7f599c4 100644 (file)
@@ -141,9 +141,11 @@ void _kvmppc_save_tm_pr(struct kvm_vcpu *vcpu, u64 guest_msr);
 extern s32 patch__call_flush_count_cache;
 extern s32 patch__flush_count_cache_return;
 extern s32 patch__flush_link_stack_return;
+extern s32 patch__call_kvm_flush_link_stack;
 extern s32 patch__memset_nocache, patch__memcpy_nocache;
 
 extern long flush_count_cache;
+extern long kvm_flush_link_stack;
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv);
index a3138e7d71bb6f4c7b78c238e490305963bbab3c..bd91dceb70105aa207d45fc4a86d3517ee804d18 100644 (file)
@@ -400,6 +400,9 @@ static void toggle_count_cache_flush(bool enable)
 
        if (!enable) {
                patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP);
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+               patch_instruction_site(&patch__call_kvm_flush_link_stack, PPC_INST_NOP);
+#endif
                pr_info("link-stack-flush: software flush disabled.\n");
                link_stack_flush_enabled = false;
                no_count_cache_flush();
@@ -410,6 +413,12 @@ static void toggle_count_cache_flush(bool enable)
        patch_branch_site(&patch__call_flush_count_cache,
                          (u64)&flush_count_cache, BRANCH_SET_LINK);
 
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+       // This enables the branch from guest_exit_cont to kvm_flush_link_stack
+       patch_branch_site(&patch__call_kvm_flush_link_stack,
+                         (u64)&kvm_flush_link_stack, BRANCH_SET_LINK);
+#endif
+
        pr_info("link-stack-flush: software flush enabled.\n");
        link_stack_flush_enabled = true;
 
index 07181d0dfcb79a0b582d1e8b3af2569955969d0f..0ba1d7abb7980c9becf767117b0b5539f989a7eb 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <asm/ppc_asm.h>
+#include <asm/code-patching-asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
 #include <asm/mmu.h>
@@ -1458,6 +1459,13 @@ guest_exit_cont:         /* r9 = vcpu, r12 = trap, r13 = paca */
 1:
 #endif /* CONFIG_KVM_XICS */
 
+       /*
+        * Possibly flush the link stack here, before we do a blr in
+        * guest_exit_short_path.
+        */
+1:     nop
+       patch_site 1b patch__call_kvm_flush_link_stack
+
        /* If we came in through the P9 short path, go back out to C now */
        lwz     r0, STACK_SLOT_SHORT_PATH(r1)
        cmpwi   r0, 0
@@ -1933,6 +1941,28 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        mtlr    r0
        blr
 
+.balign 32
+.global kvm_flush_link_stack
+kvm_flush_link_stack:
+       /* Save LR into r0 */
+       mflr    r0
+
+       /* Flush the link stack. On Power8 it's up to 32 entries in size. */
+       .rept 32
+       bl      .+4
+       .endr
+
+       /* And on Power9 it's up to 64. */
+BEGIN_FTR_SECTION
+       .rept 32
+       bl      .+4
+       .endr
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
+       /* Restore LR */
+       mtlr    r0
+       blr
+
 kvmppc_guest_external:
        /* External interrupt, first check for host_ipi. If this is
         * set, we know the host wants us out so let's do it now