| From a618486444bfe6f235f76ff547eec914f5dda9ce Mon Sep 17 00:00:00 2001 |
| From: Daniel Sneddon <daniel.sneddon@linux.intel.com> |
| Date: Tue, 1 Aug 2023 16:36:26 +0200 |
| Subject: x86/speculation: Add force option to GDS mitigation |
| |
| From: Daniel Sneddon <daniel.sneddon@linux.intel.com> |
| |
| commit 553a5c03e90a6087e88f8ff878335ef0621536fb upstream |
| |
| The Gather Data Sampling (GDS) vulnerability allows malicious software |
| to infer stale data previously stored in vector registers. This may |
| include sensitive data such as cryptographic keys. GDS is mitigated in |
| microcode, and systems with up-to-date microcode are protected by |
| default. However, any affected system that is running with older |
| microcode will still be vulnerable to GDS attacks. |
| |
| Since the gather instructions used by the attacker are part of the |
| AVX2 and AVX512 extensions, disabling these extensions prevents gather |
| instructions from being executed, thereby mitigating the system from |
| GDS. Disabling AVX2 is sufficient, but we don't have the granularity |
| to do this. The XCR0[2] disables AVX, with no option to just disable |
| AVX2. |
| |
| Add a kernel parameter gather_data_sampling=force that will enable the |
| microcode mitigation if available, otherwise it will disable AVX on |
| affected systems. |
| |
| This option will be ignored if cmdline mitigations=off. |
| |
| This is a *big* hammer. It is known to break buggy userspace that |
| uses incomplete, buggy AVX enumeration. Unfortunately, such userspace |
| does exist in the wild: |
| |
| https://www.mail-archive.com/bug-coreutils@gnu.org/msg33046.html |
| |
| [ dhansen: add some more ominous warnings about disabling AVX ] |
| |
| Signed-off-by: Daniel Sneddon <daniel.sneddon@linux.intel.com> |
| Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> |
| Acked-by: Josh Poimboeuf <jpoimboe@kernel.org> |
| Signed-off-by: Daniel Sneddon <daniel.sneddon@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| Documentation/admin-guide/hw-vuln/gather_data_sampling.rst | 18 +++++++++-- |
| Documentation/admin-guide/kernel-parameters.txt | 8 ++++- |
| arch/x86/kernel/cpu/bugs.c | 20 ++++++++++++- |
| 3 files changed, 40 insertions(+), 6 deletions(-) |
| |
| --- a/Documentation/admin-guide/hw-vuln/gather_data_sampling.rst |
| +++ b/Documentation/admin-guide/hw-vuln/gather_data_sampling.rst |
| @@ -60,14 +60,21 @@ bits: |
| ================================ === ============================ |
| |
| GDS can also be mitigated on systems that don't have updated microcode by |
| -disabling AVX. This can be done by setting "clearcpuid=avx" on the kernel |
| -command-line. |
| +disabling AVX. This can be done by setting gather_data_sampling="force" or |
| +"clearcpuid=avx" on the kernel command-line. |
| + |
| +If used, these options will disable AVX use by turning on XSAVE YMM support. |
| +However, the processor will still enumerate AVX support. Userspace that |
| +does not follow proper AVX enumeration to check both AVX *and* XSAVE YMM |
| +support will break. |
| |
| Mitigation control on the kernel command line |
| --------------------------------------------- |
| The mitigation can be disabled by setting "gather_data_sampling=off" or |
| -"mitigations=off" on the kernel command line. Not specifying either will |
| -default to the mitigation being enabled. |
| +"mitigations=off" on the kernel command line. Not specifying either will default |
| +to the mitigation being enabled. Specifying "gather_data_sampling=force" will |
| +use the microcode mitigation when available or disable AVX on affected systems |
| +where the microcode hasn't been updated to include the mitigation. |
| |
| GDS System Information |
| ------------------------ |
| @@ -83,6 +90,9 @@ The possible values contained in this fi |
| Vulnerable Processor vulnerable and mitigation disabled. |
| Vulnerable: No microcode Processor vulnerable and microcode is missing |
| mitigation. |
| + Mitigation: AVX disabled, |
| + no microcode Processor is vulnerable and microcode is missing |
| + mitigation. AVX disabled as mitigation. |
| Mitigation: Microcode Processor is vulnerable and mitigation is in |
| effect. |
| Mitigation: Microcode (locked) Processor is vulnerable and mitigation is in |
| --- a/Documentation/admin-guide/kernel-parameters.txt |
| +++ b/Documentation/admin-guide/kernel-parameters.txt |
| @@ -1603,7 +1603,13 @@ |
| |
| This issue is mitigated by default in updated microcode. |
| The mitigation may have a performance impact but can be |
| - disabled. |
| + disabled. On systems without the microcode mitigation |
| + disabling AVX serves as a mitigation. |
| + |
| + force: Disable AVX to mitigate systems without |
| + microcode mitigation. No effect if the microcode |
| + mitigation is present. Known to cause crashes in |
| + userspace with buggy AVX enumeration. |
| |
| off: Disable GDS mitigation. |
| |
| --- a/arch/x86/kernel/cpu/bugs.c |
| +++ b/arch/x86/kernel/cpu/bugs.c |
| @@ -652,6 +652,7 @@ early_param("l1d_flush", l1d_flush_parse |
| enum gds_mitigations { |
| GDS_MITIGATION_OFF, |
| GDS_MITIGATION_UCODE_NEEDED, |
| + GDS_MITIGATION_FORCE, |
| GDS_MITIGATION_FULL, |
| GDS_MITIGATION_FULL_LOCKED, |
| GDS_MITIGATION_HYPERVISOR, |
| @@ -662,6 +663,7 @@ static enum gds_mitigations gds_mitigati |
| static const char * const gds_strings[] = { |
| [GDS_MITIGATION_OFF] = "Vulnerable", |
| [GDS_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode", |
| + [GDS_MITIGATION_FORCE] = "Mitigation: AVX disabled, no microcode", |
| [GDS_MITIGATION_FULL] = "Mitigation: Microcode", |
| [GDS_MITIGATION_FULL_LOCKED] = "Mitigation: Microcode (locked)", |
| [GDS_MITIGATION_HYPERVISOR] = "Unknown: Dependent on hypervisor status", |
| @@ -687,6 +689,7 @@ void update_gds_msr(void) |
| rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); |
| mcu_ctrl &= ~GDS_MITG_DIS; |
| break; |
| + case GDS_MITIGATION_FORCE: |
| case GDS_MITIGATION_UCODE_NEEDED: |
| case GDS_MITIGATION_HYPERVISOR: |
| return; |
| @@ -721,10 +724,23 @@ static void __init gds_select_mitigation |
| |
| /* No microcode */ |
| if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) { |
| - gds_mitigation = GDS_MITIGATION_UCODE_NEEDED; |
| + if (gds_mitigation == GDS_MITIGATION_FORCE) { |
| + /* |
| + * This only needs to be done on the boot CPU so do it |
| + * here rather than in update_gds_msr() |
| + */ |
| + setup_clear_cpu_cap(X86_FEATURE_AVX); |
| + pr_warn("Microcode update needed! Disabling AVX as mitigation.\n"); |
| + } else { |
| + gds_mitigation = GDS_MITIGATION_UCODE_NEEDED; |
| + } |
| goto out; |
| } |
| |
| + /* Microcode has mitigation, use it */ |
| + if (gds_mitigation == GDS_MITIGATION_FORCE) |
| + gds_mitigation = GDS_MITIGATION_FULL; |
| + |
| rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); |
| if (mcu_ctrl & GDS_MITG_LOCKED) { |
| if (gds_mitigation == GDS_MITIGATION_OFF) |
| @@ -755,6 +771,8 @@ static int __init gds_parse_cmdline(char |
| |
| if (!strcmp(str, "off")) |
| gds_mitigation = GDS_MITIGATION_OFF; |
| + else if (!strcmp(str, "force")) |
| + gds_mitigation = GDS_MITIGATION_FORCE; |
| |
| return 0; |
| } |