Skip to content

Commit 39e72bf

Browse files
committed
powerpc/book3s64: Fix link stack flush on context switch
In commit ee13cb2 ("powerpc/64s: Add support for software count cache flush"), I added support for software to flush the count cache (indirect branch cache) on context switch if firmware told us that was the required mitigation for Spectre v2. As part of that code we also added a software flush of the link stack (return address stack), which protects against Spectre-RSB between user processes. That is all correct for CPUs that activate that mitigation, which is currently Power9 Nimbus DD2.3. What I got wrong is that on older CPUs, where firmware has disabled the count cache, we also need to flush the link stack on context switch. To fix it we create a new feature bit which is not set by firmware, which tells us we need to flush the link stack. We set that when firmware tells us that either of the existing Spectre v2 mitigations are enabled. Then we adjust the patching code so that if we see that feature bit we enable the link stack flush. If we're also told to flush the count cache in software then we fall through and do that also. On the older CPUs we don't need to do do the software count cache flush, firmware has disabled it, so in that case we patch in an early return after the link stack flush. The naming of some of the functions is awkward after this patch, because they're called "count cache" but they also do link stack. But we'll fix that up in a later commit to ease backporting. This is the fix for CVE-2019-18660. Reported-by: Anthony Steinhauser <[email protected]> Fixes: ee13cb2 ("powerpc/64s: Add support for software count cache flush") Cc: [email protected] # v4.4+ Signed-off-by: Michael Ellerman <[email protected]>
1 parent 31f4f5b commit 39e72bf

File tree

4 files changed

+54
-4
lines changed

4 files changed

+54
-4
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ void _kvmppc_save_tm_pr(struct kvm_vcpu *vcpu, u64 guest_msr);
152152
/* Patch sites */
153153
extern s32 patch__call_flush_count_cache;
154154
extern s32 patch__flush_count_cache_return;
155+
extern s32 patch__flush_link_stack_return;
155156
extern s32 patch__memset_nocache, patch__memcpy_nocache;
156157

157158
extern long flush_count_cache;

arch/powerpc/include/asm/security_features.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ static inline bool security_ftr_enabled(unsigned long feature)
8181
// Software required to flush count cache on context switch
8282
#define SEC_FTR_FLUSH_COUNT_CACHE 0x0000000000000400ull
8383

84+
// Software required to flush link stack on context switch
85+
#define SEC_FTR_FLUSH_LINK_STACK 0x0000000000001000ull
86+
8487

8588
// Features enabled by default
8689
#define SEC_FTR_DEFAULT \

arch/powerpc/kernel/entry_64.S

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ flush_count_cache:
537537
/* Save LR into r9 */
538538
mflr r9
539539

540+
// Flush the link stack
540541
.rept 64
541542
bl .+4
542543
.endr
@@ -546,6 +547,11 @@ flush_count_cache:
546547
.balign 32
547548
/* Restore LR */
548549
1: mtlr r9
550+
551+
// If we're just flushing the link stack, return here
552+
3: nop
553+
patch_site 3b patch__flush_link_stack_return
554+
549555
li r9,0x7fff
550556
mtctr r9
551557

arch/powerpc/kernel/security.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ enum count_cache_flush_type {
2424
COUNT_CACHE_FLUSH_HW = 0x4,
2525
};
2626
static enum count_cache_flush_type count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
27+
static bool link_stack_flush_enabled;
2728

2829
bool barrier_nospec_enabled;
2930
static bool no_nospec;
@@ -212,11 +213,19 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
212213

213214
if (ccd)
214215
seq_buf_printf(&s, "Indirect branch cache disabled");
216+
217+
if (link_stack_flush_enabled)
218+
seq_buf_printf(&s, ", Software link stack flush");
219+
215220
} else if (count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) {
216221
seq_buf_printf(&s, "Mitigation: Software count cache flush");
217222

218223
if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW)
219224
seq_buf_printf(&s, " (hardware accelerated)");
225+
226+
if (link_stack_flush_enabled)
227+
seq_buf_printf(&s, ", Software link stack flush");
228+
220229
} else if (btb_flush_enabled) {
221230
seq_buf_printf(&s, "Mitigation: Branch predictor state flush");
222231
} else {
@@ -377,18 +386,40 @@ static __init int stf_barrier_debugfs_init(void)
377386
device_initcall(stf_barrier_debugfs_init);
378387
#endif /* CONFIG_DEBUG_FS */
379388

389+
static void no_count_cache_flush(void)
390+
{
391+
count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
392+
pr_info("count-cache-flush: software flush disabled.\n");
393+
}
394+
380395
static void toggle_count_cache_flush(bool enable)
381396
{
382-
if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
397+
if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE) &&
398+
!security_ftr_enabled(SEC_FTR_FLUSH_LINK_STACK))
399+
enable = false;
400+
401+
if (!enable) {
383402
patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP);
384-
count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
385-
pr_info("count-cache-flush: software flush disabled.\n");
403+
pr_info("link-stack-flush: software flush disabled.\n");
404+
link_stack_flush_enabled = false;
405+
no_count_cache_flush();
386406
return;
387407
}
388408

409+
// This enables the branch from _switch to flush_count_cache
389410
patch_branch_site(&patch__call_flush_count_cache,
390411
(u64)&flush_count_cache, BRANCH_SET_LINK);
391412

413+
pr_info("link-stack-flush: software flush enabled.\n");
414+
link_stack_flush_enabled = true;
415+
416+
// If we just need to flush the link stack, patch an early return
417+
if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
418+
patch_instruction_site(&patch__flush_link_stack_return, PPC_INST_BLR);
419+
no_count_cache_flush();
420+
return;
421+
}
422+
392423
if (!security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) {
393424
count_cache_flush_type = COUNT_CACHE_FLUSH_SW;
394425
pr_info("count-cache-flush: full software flush sequence enabled.\n");
@@ -407,11 +438,20 @@ void setup_count_cache_flush(void)
407438
if (no_spectrev2 || cpu_mitigations_off()) {
408439
if (security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED) ||
409440
security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED))
410-
pr_warn("Spectre v2 mitigations not under software control, can't disable\n");
441+
pr_warn("Spectre v2 mitigations not fully under software control, can't disable\n");
411442

412443
enable = false;
413444
}
414445

446+
/*
447+
* There's no firmware feature flag/hypervisor bit to tell us we need to
448+
* flush the link stack on context switch. So we set it here if we see
449+
* either of the Spectre v2 mitigations that aim to protect userspace.
450+
*/
451+
if (security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED) ||
452+
security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE))
453+
security_ftr_set(SEC_FTR_FLUSH_LINK_STACK);
454+
415455
toggle_count_cache_flush(enable);
416456
}
417457

0 commit comments

Comments
 (0)