IBPB currently is applied to all tasks. However, when spectre_v2_app2app_enabled is set to default value SPECTRE_V2_APP2APP_PRCTL, only tasks marked with TIF_SPEC_BRANCH_SPECULATION via prctl are protected against Spectre V2 sibling thread attack to minimize performance impact. Extend this option to IBPB to protect only tasks marked with TIF_SPEC_BRANCH_SPECULATION needing mitigation to minimize performance impact. Make IBPB usage follow the spectre_v2_app2app_enabled option: spectre_v2_app2app = SPECTRE_V2_APP2APP_PRCTL : Use IBPB only on tasks with TIF_SPEC_BRANCH_SPECULATION SPECTRE_V2_APP2APP_STRICT : Use IBPB on all tasks SPECTRE_V2_APP2APP_NONE : Don't use IBPB Signed-off-by: Tim Chen <tim.c.chen@xxxxxxxxxxxxxxx> --- arch/x86/kernel/cpu/bugs.c | 29 ++++++++++++++++++----------- arch/x86/mm/tlb.c | 23 ++++++++++++++++++----- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 26e1a87..44f7127 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -534,12 +534,6 @@ static void __init spectre_v2_select_mitigation(void) setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW); pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n"); - /* Initialize Indirect Branch Prediction Barrier if supported */ - if (boot_cpu_has(X86_FEATURE_IBPB)) { - setup_force_cpu_cap(X86_FEATURE_USE_IBPB); - pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n"); - } - /* * Retpoline means the kernel is safe because it has no indirect * branches. Enhanced IBRS protects firmware too, so, enable restricted @@ -558,8 +552,9 @@ static void __init spectre_v2_select_mitigation(void) app2app_mode = SPECTRE_V2_APP2APP_NONE; - /* No mitigation if mitigation feature is unavailable */ - if (!boot_cpu_has(X86_FEATURE_STIBP)) + /* No mitigation if all mitigation features are unavailable */ + if (!boot_cpu_has(X86_FEATURE_IBPB) && + !boot_cpu_has(X86_FEATURE_STIBP)) goto set_app2app_mode; app2app_cmd = spectre_v2_parse_app2app_cmdline(cmd); @@ -587,6 +582,16 @@ static void __init spectre_v2_select_mitigation(void) break; } + /* + * Initialize Indirect Branch Prediction Barrier if supported + * and not disabled explicitly + */ + if (boot_cpu_has(X86_FEATURE_IBPB) && + app2app_mode != SPECTRE_V2_APP2APP_NONE) { + setup_force_cpu_cap(X86_FEATURE_USE_IBPB); + pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n"); + } + set_app2app_mode: spectre_v2_app2app_enabled = app2app_mode; pr_info("%s\n", spectre_v2_app2app_strings[app2app_mode]); @@ -1076,10 +1081,12 @@ static char *stibp_state(void) static char *ibpb_state(void) { - if (boot_cpu_has(X86_FEATURE_USE_IBPB)) - return ", IBPB"; - else + if (spectre_v2_app2app_enabled == SPECTRE_V2_APP2APP_NONE) return ""; + else if (spectre_v2_app2app_enabled == SPECTRE_V2_APP2APP_PRCTL) + return ", IBPB-prctl"; + else + return ", IBPB-all"; } static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index bddd6b3..616694c 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -184,14 +184,27 @@ static void sync_current_stack_to_mm(struct mm_struct *mm) static bool ibpb_needed(struct task_struct *tsk, u64 last_ctx_id) { /* - * Check if the current (previous) task has access to the memory - * of the @tsk (next) task. If access is denied, make sure to - * issue a IBPB to stop user->user Spectre-v2 attacks. + * Don't issue IBPB when switching to kernel threads or staying in the + * same mm context. + */ + if (!tsk || !tsk->mm || tsk->mm->context.ctx_id == last_ctx_id) + return false; + + /* + * If lite protection mode is enabled, check the STIBP thread flag. + * + * Otherwise check if the current (previous) task has access to the + * the memory of the @tsk (next) task for strict app to app protection. + * If access is denied, make sure to issue a IBPB to stop user->user + * Spectre-v2 attacks. * * Note: __ptrace_may_access() returns 0 or -ERRNO. */ - return (tsk && tsk->mm && tsk->mm->context.ctx_id != last_ctx_id && - ptrace_may_access_sched(tsk, PTRACE_MODE_SPEC_IBPB)); + + if (static_branch_unlikely(&spectre_v2_app_lite)) + return test_tsk_thread_flag(tsk, TIF_SPEC_INDIR_BRANCH); + else + return ptrace_may_access_sched(tsk, PTRACE_MODE_SPEC_IBPB); } void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, -- 2.9.4