Skip to content
GoogleGHSA-9x5g-vmxf-4qj8

Linux Kernel: Bypassing Spectre-BTI User Space Mitigations

LowCVE-2023-0045 · Published Feb 3, 2023 · updated Feb 7, 2023

### Summary When testing the success rate of Spectre-BTI attacks, we detected a strange pattern when using the kernel API as mitigation [[1](https://docs.kernel.org/userspace-api/spec_ctrl.html)]. Our tests revealed that the Linux kernel fails to correctly mitigate the attack leaving the process exposed for a short period of time after the syscall. Further investigation showed that the kernel does not issue an IBPB immediately during the syscall. The ```ib_prctl_set``` [[2](https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1467)] function updates the Thread Information Flags (TIFs) for the task and updates the SPEC_CTRL MSR on the function ```__speculation_ctrl_update``` [[3]([https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1467])], but the IBPB is only issued on the next schedule, when the TIF bits are checked. This leaves the victim vulnerable to values already injected on the BTB, prior to the prctl syscall. The behavior is only corrected after a reschedule of the taks happens. Furthermore, the kernel entrance (due to the syscall itself), does not issue an IBPB in the default scenarios (i.e., when the kernel protects itself...

GitHub advisory

Affected versions

PackageAffectedFixed in
Kernel
Product
< e8377f0456fb6738a4668d4df16c13d7599925fde8377f0456fb6738a4668d4df16c13d7599925fd
Details and references

### Summary When testing the success rate of Spectre-BTI attacks, we detected a strange pattern when using the kernel API as mitigation [[1](https://docs.kernel.org/userspace-api/spec_ctrl.html)]. Our tests revealed that the Linux kernel fails to correctly mitigate the attack leaving the process exposed for a short period of time after the syscall. Further investigation showed that the kernel does not issue an IBPB immediately during the syscall. The ```ib_prctl_set``` [[2](https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1467)] function updates the Thread Information Flags (TIFs) for the task and updates the SPEC_CTRL MSR on the function ```__speculation_ctrl_update``` [[3]([https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1467])], but the IBPB is only issued on the next schedule, when the TIF bits are checked. This leaves the victim vulnerable to values already injected on the BTB, prior to the prctl syscall. The behavior is only corrected after a reschedule of the taks happens. Furthermore, the kernel entrance (due to the syscall itself), does not issue an IBPB in the default scenarios (i.e., when the kernel protects itself via retpoline or eIBRS). Executing a prctl to mitigate spectre-BTI attacks using: ``` prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);``` leads to the``` ib_prctl_set``` [[2](https://elixir.bootlin.com/linux/v5.15.56/source/arch/x86/kernel/cpu/bugs.c#L1467)] function on kernel 5.15. When the option SPEC_DISABLE is used the TIF bit for ```task_set_spec_ib_disable``` is set and ```task_update_spec_tif``` is called: ``` static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) [...] case PR_SPEC_FORCE_DISABLE: /* * Indirect branch speculation is always allowed when * mitigation is force disabled. */ if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) return -EPERM; if (!is_spec_ib_user_controlled()) return 0; task_set_spec_ib_disable(task); if (ctrl == PR_SPEC_FORCE_DISABLE) task_set_spec_ib_force_disable(task); task_update_spec_tif(task); break; ``` ``` ```task_set_spec_ib_disable``` calls ```set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE);``` and if the target task is the current process it calls ``` speculation_ctrl_update_current(); ``` ``` static void task_update_spec_tif(struct task_struct *tsk) { /* Force the update of the real TIF bits */ set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE); /* * Immediately update the speculation control MSRs for the current * task, but for a non-current task delay setting the CPU * mitigation until it is scheduled next. * * This can only happen for SECCOMP mitigation. For PRCTL it's * always the current task. */ if (tsk == current) speculation_ctrl_update_current(); } ``` The ``` speculation_ctrl_update_current``` after the ```speculation_ctrl_update``` wrapper executes ```__speculation_ctrl_update``` with ```tifp = ~tifp``` , here the update of the wrmsr for setting STIBP is executed but no IBPB is issued : ``` static __always_inline void __speculation_ctrl_update(unsigned long tifp, unsigned long tifn) { unsigned long tif_diff = tifp ^ tifn; u64 msr = x86_spec_ctrl_base; bool updmsr = false; lockdep_assert_irqs_disabled(); /* Handle change of TIF_SSBD depending on the mitigation method. */ if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) { if (tif_diff & _TIF_SSBD) amd_set_ssb_virt_state(tifn); } else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) { if (tif_diff & _TIF_SSBD) amd_set_core_ssb_state(tifn); } else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) || static_cpu_has(X86_FEATURE_AMD_SSBD)) { updmsr |= !!(tif_diff & _TIF_SSBD); msr |= ssbd_tif_to_spec_ctrl(tifn); } /* Only evaluate TIF_SPEC_IB if conditional STIBP is enabled. */ if (IS_ENABLED(CONFIG_SMP) && static_branch_unlikely(&switch_to_cond_stibp)) {

Severity from
GitHub (reviewed advisory)

More Google advisories

All Google
Advisory
Linux Kernel: Spectre v2 SMT mitigations problem
MediumApr 12, 2023
CISCO: ClamAV Heap Buffer Overflow
HighFeb 21, 2023
Amazon: RDS SQL Server
MediumJan 30, 2023
Unsandboxed Password Manager
HighJan 17, 2023
Linux Kernel: Infoleak in Bluetooth L2CAP Handling
MediumNov 29, 2022
Linux Kernel: UAF in Bluetooth L2CAP Handshake
MediumNov 29, 2022

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.