Skip to content

Commit af2e8c6

Browse files
committed
KVM: PPC: Book3S HV: Flush link stack on guest exit to host kernel
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 <[email protected]>
1 parent 39e72bf commit af2e8c6

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

arch/powerpc/include/asm/asm-prototypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,11 @@ void _kvmppc_save_tm_pr(struct kvm_vcpu *vcpu, u64 guest_msr);
153153
extern s32 patch__call_flush_count_cache;
154154
extern s32 patch__flush_count_cache_return;
155155
extern s32 patch__flush_link_stack_return;
156+
extern s32 patch__call_kvm_flush_link_stack;
156157
extern s32 patch__memset_nocache, patch__memcpy_nocache;
157158

158159
extern long flush_count_cache;
160+
extern long kvm_flush_link_stack;
159161

160162
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
161163
void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv);

arch/powerpc/kernel/security.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ static void toggle_count_cache_flush(bool enable)
400400

401401
if (!enable) {
402402
patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP);
403+
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
404+
patch_instruction_site(&patch__call_kvm_flush_link_stack, PPC_INST_NOP);
405+
#endif
403406
pr_info("link-stack-flush: software flush disabled.\n");
404407
link_stack_flush_enabled = false;
405408
no_count_cache_flush();
@@ -410,6 +413,12 @@ static void toggle_count_cache_flush(bool enable)
410413
patch_branch_site(&patch__call_flush_count_cache,
411414
(u64)&flush_count_cache, BRANCH_SET_LINK);
412415

416+
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
417+
// This enables the branch from guest_exit_cont to kvm_flush_link_stack
418+
patch_branch_site(&patch__call_kvm_flush_link_stack,
419+
(u64)&kvm_flush_link_stack, BRANCH_SET_LINK);
420+
#endif
421+
413422
pr_info("link-stack-flush: software flush enabled.\n");
414423
link_stack_flush_enabled = true;
415424

arch/powerpc/kvm/book3s_hv_rmhandlers.S

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
*/
1212

1313
#include <asm/ppc_asm.h>
14+
#include <asm/code-patching-asm.h>
1415
#include <asm/kvm_asm.h>
1516
#include <asm/reg.h>
1617
#include <asm/mmu.h>
@@ -1487,6 +1488,13 @@ guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */
14871488
1:
14881489
#endif /* CONFIG_KVM_XICS */
14891490

1491+
/*
1492+
* Possibly flush the link stack here, before we do a blr in
1493+
* guest_exit_short_path.
1494+
*/
1495+
1: nop
1496+
patch_site 1b patch__call_kvm_flush_link_stack
1497+
14901498
/* If we came in through the P9 short path, go back out to C now */
14911499
lwz r0, STACK_SLOT_SHORT_PATH(r1)
14921500
cmpwi r0, 0
@@ -1963,6 +1971,28 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
19631971
mtlr r0
19641972
blr
19651973

1974+
.balign 32
1975+
.global kvm_flush_link_stack
1976+
kvm_flush_link_stack:
1977+
/* Save LR into r0 */
1978+
mflr r0
1979+
1980+
/* Flush the link stack. On Power8 it's up to 32 entries in size. */
1981+
.rept 32
1982+
bl .+4
1983+
.endr
1984+
1985+
/* And on Power9 it's up to 64. */
1986+
BEGIN_FTR_SECTION
1987+
.rept 32
1988+
bl .+4
1989+
.endr
1990+
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
1991+
1992+
/* Restore LR */
1993+
mtlr r0
1994+
blr
1995+
19661996
kvmppc_guest_external:
19671997
/* External interrupt, first check for host_ipi. If this is
19681998
* set, we know the host wants us out so let's do it now

0 commit comments

Comments
 (0)