powerpc fixes for Spectre-RSB
We failed to activate the mitigation for Spectre-RSB (Return Stack Buffer, aka. ret2spec) on context switch, on CPUs prior to Power9 DD2.3. That allows a process to poison the RSB (called Link Stack on Power CPUs) and possibly misdirect speculative execution of another process. If the victim process can be induced to execute a leak gadget then it may be possible to extract information from the victim via a side channel. The fix is to correctly activate the link stack flush mitigation on all CPUs that have any mitigation of Spectre v2 in userspace enabled. There's a second commit which adds a link stack flush in the KVM guest exit path. A leak via that path has not been demonstrated, but we believe it's at least theoretically possible. This is the fix for CVE-2019-18660. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAl3eUXsTHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgEXtD/4qiCp4OHo+MEFbDyqZHZSYdFihpZ2B 9s8yQKMaL0WWVJU0rlKSY0fDW/W0pLUn1zoREY9kRIHrQQi9wd5kg6s2kZtDeIPZ XPANeOpicMJjKGA+s/CqJfJZmGhzQ6VYplg/qevjvgOZqn8QsQhljg85w3Tr2wjo oXyi/0ZNv957pYrTHu08YIRr5OxalcE6Cxb4hZBqwbcubwKANSifLb72hcDEkNdR wshmt6mZUMtW8ToaGGt2b0csF2I0TClvBLQV8bxlbMZNFPYgUfBaHyCtHnv6bX65 Jlgyw46pv9o0aeIF24rmP9jDEX+Hcig5Qu/EdLkd9lDl5YMxxVv9LlGq8tt7TQjI J97DeUFYjvePGMzirPFc7EvEoN35f19/5IuZUEQQ8wE4I/R1gNqOxbpGUqvReTbA +WJHqqT6sbJ1ys/mWRlGYMkn1xPNG3scpTNNh9/f3f/+ci3knOeYNeieVjjFvIv0 4+toMQGIU7gB0mU67oLyClygOvC0DeBSQk8nFk0pznzUqdQlsqnbbI5O0KWFjf57 jZV9l5khfdkkZiTIkGEZ3RY7X4pcrKd4kI+5+2OLiZOQVw2rudE3+ocysxP0osmA Ec+dr3uxL1YKdR4GVvk5mCMNlln6PpfT5Y21YSiipnGsWC1hvYkbPaj4u/T5oV5T B1bP/R7gQw4yfQ== =NQFt -----END PGP SIGNATURE----- Merge tag 'powerpc-spectre-rsb' of powerpc-CVE-2019-18660.bundle Pull powerpc Spectre-RSB fixes from Michael Ellerman: "We failed to activate the mitigation for Spectre-RSB (Return Stack Buffer, aka. ret2spec) on context switch, on CPUs prior to Power9 DD2.3. That allows a process to poison the RSB (called Link Stack on Power CPUs) and possibly misdirect speculative execution of another process. If the victim process can be induced to execute a leak gadget then it may be possible to extract information from the victim via a side channel. The fix is to correctly activate the link stack flush mitigation on all CPUs that have any mitigation of Spectre v2 in userspace enabled. There's a second commit which adds a link stack flush in the KVM guest exit path. A leak via that path has not been demonstrated, but we believe it's at least theoretically possible. This is the fix for CVE-2019-18660" * tag 'powerpc-spectre-rsb' of /home/torvalds/Downloads/powerpc-CVE-2019-18660.bundle: KVM: PPC: Book3S HV: Flush link stack on guest exit to host kernel powerpc/book3s64: Fix link stack flush on context switch
This commit is contained in:
commit
80eb5fea3c
|
@ -152,9 +152,12 @@ void _kvmppc_save_tm_pr(struct kvm_vcpu *vcpu, u64 guest_msr);
|
|||
/* Patch sites */
|
||||
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);
|
||||
|
|
|
@ -81,6 +81,9 @@ static inline bool security_ftr_enabled(unsigned long feature)
|
|||
// Software required to flush count cache on context switch
|
||||
#define SEC_FTR_FLUSH_COUNT_CACHE 0x0000000000000400ull
|
||||
|
||||
// Software required to flush link stack on context switch
|
||||
#define SEC_FTR_FLUSH_LINK_STACK 0x0000000000001000ull
|
||||
|
||||
|
||||
// Features enabled by default
|
||||
#define SEC_FTR_DEFAULT \
|
||||
|
|
|
@ -537,6 +537,7 @@ flush_count_cache:
|
|||
/* Save LR into r9 */
|
||||
mflr r9
|
||||
|
||||
// Flush the link stack
|
||||
.rept 64
|
||||
bl .+4
|
||||
.endr
|
||||
|
@ -546,6 +547,11 @@ flush_count_cache:
|
|||
.balign 32
|
||||
/* Restore LR */
|
||||
1: mtlr r9
|
||||
|
||||
// If we're just flushing the link stack, return here
|
||||
3: nop
|
||||
patch_site 3b patch__flush_link_stack_return
|
||||
|
||||
li r9,0x7fff
|
||||
mtctr r9
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ enum count_cache_flush_type {
|
|||
COUNT_CACHE_FLUSH_HW = 0x4,
|
||||
};
|
||||
static enum count_cache_flush_type count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
|
||||
static bool link_stack_flush_enabled;
|
||||
|
||||
bool barrier_nospec_enabled;
|
||||
static bool no_nospec;
|
||||
|
@ -212,11 +213,19 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
|
|||
|
||||
if (ccd)
|
||||
seq_buf_printf(&s, "Indirect branch cache disabled");
|
||||
|
||||
if (link_stack_flush_enabled)
|
||||
seq_buf_printf(&s, ", Software link stack flush");
|
||||
|
||||
} else if (count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) {
|
||||
seq_buf_printf(&s, "Mitigation: Software count cache flush");
|
||||
|
||||
if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW)
|
||||
seq_buf_printf(&s, " (hardware accelerated)");
|
||||
|
||||
if (link_stack_flush_enabled)
|
||||
seq_buf_printf(&s, ", Software link stack flush");
|
||||
|
||||
} else if (btb_flush_enabled) {
|
||||
seq_buf_printf(&s, "Mitigation: Branch predictor state flush");
|
||||
} else {
|
||||
|
@ -377,18 +386,49 @@ static __init int stf_barrier_debugfs_init(void)
|
|||
device_initcall(stf_barrier_debugfs_init);
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static void no_count_cache_flush(void)
|
||||
{
|
||||
count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
|
||||
pr_info("count-cache-flush: software flush disabled.\n");
|
||||
}
|
||||
|
||||
static void toggle_count_cache_flush(bool enable)
|
||||
{
|
||||
if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
|
||||
if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE) &&
|
||||
!security_ftr_enabled(SEC_FTR_FLUSH_LINK_STACK))
|
||||
enable = false;
|
||||
|
||||
if (!enable) {
|
||||
patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP);
|
||||
count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
|
||||
pr_info("count-cache-flush: software flush disabled.\n");
|
||||
#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();
|
||||
return;
|
||||
}
|
||||
|
||||
// This enables the branch from _switch to flush_count_cache
|
||||
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;
|
||||
|
||||
// If we just need to flush the link stack, patch an early return
|
||||
if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
|
||||
patch_instruction_site(&patch__flush_link_stack_return, PPC_INST_BLR);
|
||||
no_count_cache_flush();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) {
|
||||
count_cache_flush_type = COUNT_CACHE_FLUSH_SW;
|
||||
pr_info("count-cache-flush: full software flush sequence enabled.\n");
|
||||
|
@ -407,11 +447,20 @@ void setup_count_cache_flush(void)
|
|||
if (no_spectrev2 || cpu_mitigations_off()) {
|
||||
if (security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED) ||
|
||||
security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED))
|
||||
pr_warn("Spectre v2 mitigations not under software control, can't disable\n");
|
||||
pr_warn("Spectre v2 mitigations not fully under software control, can't disable\n");
|
||||
|
||||
enable = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* There's no firmware feature flag/hypervisor bit to tell us we need to
|
||||
* flush the link stack on context switch. So we set it here if we see
|
||||
* either of the Spectre v2 mitigations that aim to protect userspace.
|
||||
*/
|
||||
if (security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED) ||
|
||||
security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE))
|
||||
security_ftr_set(SEC_FTR_FLUSH_LINK_STACK);
|
||||
|
||||
toggle_count_cache_flush(enable);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
@ -1487,6 +1488,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
|
||||
|
@ -1963,6 +1971,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
|
||||
|
|
Loading…
Reference in New Issue