x86/speculation: Add Gather Data Sampling mitigation
Gather Data Sampling (GDS) is a hardware vulnerability which allows unprivileged speculative access to data which was previously stored in vector registers. Intel processors that support AVX2 and AVX512 have gather instructions that fetch non-contiguous data elements from memory. On vulnerable hardware, when a gather instruction is transiently executed and encounters a fault, stale data from architectural or internal vector registers may get transiently stored to the destination vector register allowing an attacker to infer the stale data using typical side channel techniques like cache timing attacks. This mitigation is different from many earlier ones for two reasons. First, it is enabled by default and a bit must be set to *DISABLE* it. This is the opposite of normal mitigation polarity. This means GDS can be mitigated simply by updating microcode and leaving the new control bit alone. Second, GDS has a "lock" bit. This lock bit is there because the mitigation affects the hardware security features KeyLocker and SGX. It needs to be enabled and *STAY* enabled for these features to be mitigated against GDS. The mitigation is enabled in the microcode by default. Disable it by setting gather_data_sampling=off or by disabling all mitigations with mitigations=off. The mitigation status can be checked by reading: /sys/devices/system/cpu/vulnerabilities/gather_data_sampling 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>
This commit is contained in:
parent
fdf0eaf114
commit
8974eb5882
|
@ -513,17 +513,18 @@ Description: information about CPUs heterogeneity.
|
||||||
cpu_capacity: capacity of cpuX.
|
cpu_capacity: capacity of cpuX.
|
||||||
|
|
||||||
What: /sys/devices/system/cpu/vulnerabilities
|
What: /sys/devices/system/cpu/vulnerabilities
|
||||||
/sys/devices/system/cpu/vulnerabilities/meltdown
|
/sys/devices/system/cpu/vulnerabilities/gather_data_sampling
|
||||||
/sys/devices/system/cpu/vulnerabilities/spectre_v1
|
/sys/devices/system/cpu/vulnerabilities/itlb_multihit
|
||||||
/sys/devices/system/cpu/vulnerabilities/spectre_v2
|
|
||||||
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
|
|
||||||
/sys/devices/system/cpu/vulnerabilities/l1tf
|
/sys/devices/system/cpu/vulnerabilities/l1tf
|
||||||
/sys/devices/system/cpu/vulnerabilities/mds
|
/sys/devices/system/cpu/vulnerabilities/mds
|
||||||
/sys/devices/system/cpu/vulnerabilities/srbds
|
/sys/devices/system/cpu/vulnerabilities/meltdown
|
||||||
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
|
|
||||||
/sys/devices/system/cpu/vulnerabilities/itlb_multihit
|
|
||||||
/sys/devices/system/cpu/vulnerabilities/mmio_stale_data
|
/sys/devices/system/cpu/vulnerabilities/mmio_stale_data
|
||||||
/sys/devices/system/cpu/vulnerabilities/retbleed
|
/sys/devices/system/cpu/vulnerabilities/retbleed
|
||||||
|
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
|
||||||
|
/sys/devices/system/cpu/vulnerabilities/spectre_v1
|
||||||
|
/sys/devices/system/cpu/vulnerabilities/spectre_v2
|
||||||
|
/sys/devices/system/cpu/vulnerabilities/srbds
|
||||||
|
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
|
||||||
Date: January 2018
|
Date: January 2018
|
||||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||||
Description: Information about CPU vulnerabilities
|
Description: Information about CPU vulnerabilities
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
GDS - Gather Data Sampling
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Gather Data Sampling is a hardware vulnerability which allows unprivileged
|
||||||
|
speculative access to data which was previously stored in vector registers.
|
||||||
|
|
||||||
|
Problem
|
||||||
|
-------
|
||||||
|
When a gather instruction performs loads from memory, different data elements
|
||||||
|
are merged into the destination vector register. However, when a gather
|
||||||
|
instruction that is transiently executed encounters a fault, stale data from
|
||||||
|
architectural or internal vector registers may get transiently forwarded to the
|
||||||
|
destination vector register instead. This will allow a malicious attacker to
|
||||||
|
infer stale data using typical side channel techniques like cache timing
|
||||||
|
attacks. GDS is a purely sampling-based attack.
|
||||||
|
|
||||||
|
The attacker uses gather instructions to infer the stale vector register data.
|
||||||
|
The victim does not need to do anything special other than use the vector
|
||||||
|
registers. The victim does not need to use gather instructions to be
|
||||||
|
vulnerable.
|
||||||
|
|
||||||
|
Because the buffers are shared between Hyper-Threads cross Hyper-Thread attacks
|
||||||
|
are possible.
|
||||||
|
|
||||||
|
Attack scenarios
|
||||||
|
----------------
|
||||||
|
Without mitigation, GDS can infer stale data across virtually all
|
||||||
|
permission boundaries:
|
||||||
|
|
||||||
|
Non-enclaves can infer SGX enclave data
|
||||||
|
Userspace can infer kernel data
|
||||||
|
Guests can infer data from hosts
|
||||||
|
Guest can infer guest from other guests
|
||||||
|
Users can infer data from other users
|
||||||
|
|
||||||
|
Because of this, it is important to ensure that the mitigation stays enabled in
|
||||||
|
lower-privilege contexts like guests and when running outside SGX enclaves.
|
||||||
|
|
||||||
|
The hardware enforces the mitigation for SGX. Likewise, VMMs should ensure
|
||||||
|
that guests are not allowed to disable the GDS mitigation. If a host erred and
|
||||||
|
allowed this, a guest could theoretically disable GDS mitigation, mount an
|
||||||
|
attack, and re-enable it.
|
||||||
|
|
||||||
|
Mitigation mechanism
|
||||||
|
--------------------
|
||||||
|
This issue is mitigated in microcode. The microcode defines the following new
|
||||||
|
bits:
|
||||||
|
|
||||||
|
================================ === ============================
|
||||||
|
IA32_ARCH_CAPABILITIES[GDS_CTRL] R/O Enumerates GDS vulnerability
|
||||||
|
and mitigation support.
|
||||||
|
IA32_ARCH_CAPABILITIES[GDS_NO] R/O Processor is not vulnerable.
|
||||||
|
IA32_MCU_OPT_CTRL[GDS_MITG_DIS] R/W Disables the mitigation
|
||||||
|
0 by default.
|
||||||
|
IA32_MCU_OPT_CTRL[GDS_MITG_LOCK] R/W Locks GDS_MITG_DIS=0. Writes
|
||||||
|
to GDS_MITG_DIS are ignored
|
||||||
|
Can't be cleared once set.
|
||||||
|
================================ === ============================
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
GDS System Information
|
||||||
|
------------------------
|
||||||
|
The kernel provides vulnerability status information through sysfs. For
|
||||||
|
GDS this can be accessed by the following sysfs file:
|
||||||
|
|
||||||
|
/sys/devices/system/cpu/vulnerabilities/gather_data_sampling
|
||||||
|
|
||||||
|
The possible values contained in this file are:
|
||||||
|
|
||||||
|
============================== =============================================
|
||||||
|
Not affected Processor not vulnerable.
|
||||||
|
Vulnerable Processor vulnerable and mitigation disabled.
|
||||||
|
Vulnerable: No microcode Processor vulnerable and microcode is missing
|
||||||
|
mitigation.
|
||||||
|
Mitigation: Microcode Processor is vulnerable and mitigation is in
|
||||||
|
effect.
|
||||||
|
Mitigation: Microcode (locked) Processor is vulnerable and mitigation is in
|
||||||
|
effect and cannot be disabled.
|
||||||
|
Unknown: Dependent on
|
||||||
|
hypervisor status Running on a virtual guest processor that is
|
||||||
|
affected but with no way to know if host
|
||||||
|
processor is mitigated or vulnerable.
|
||||||
|
============================== =============================================
|
||||||
|
|
||||||
|
GDS Default mitigation
|
||||||
|
----------------------
|
||||||
|
The updated microcode will enable the mitigation by default. The kernel's
|
||||||
|
default action is to leave the mitigation enabled.
|
|
@ -19,3 +19,4 @@ are configurable at compile, boot or run time.
|
||||||
l1d_flush.rst
|
l1d_flush.rst
|
||||||
processor_mmio_stale_data.rst
|
processor_mmio_stale_data.rst
|
||||||
cross-thread-rsb.rst
|
cross-thread-rsb.rst
|
||||||
|
gather_data_sampling.rst
|
||||||
|
|
|
@ -1623,6 +1623,20 @@
|
||||||
Format: off | on
|
Format: off | on
|
||||||
default: on
|
default: on
|
||||||
|
|
||||||
|
gather_data_sampling=
|
||||||
|
[X86,INTEL] Control the Gather Data Sampling (GDS)
|
||||||
|
mitigation.
|
||||||
|
|
||||||
|
Gather Data Sampling is a hardware vulnerability which
|
||||||
|
allows unprivileged speculative access to data which was
|
||||||
|
previously stored in vector registers.
|
||||||
|
|
||||||
|
This issue is mitigated by default in updated microcode.
|
||||||
|
The mitigation may have a performance impact but can be
|
||||||
|
disabled.
|
||||||
|
|
||||||
|
off: Disable GDS mitigation.
|
||||||
|
|
||||||
gcov_persist= [GCOV] When non-zero (default), profiling data for
|
gcov_persist= [GCOV] When non-zero (default), profiling data for
|
||||||
kernel modules is saved and remains accessible via
|
kernel modules is saved and remains accessible via
|
||||||
debugfs, even when the module is unloaded/reloaded.
|
debugfs, even when the module is unloaded/reloaded.
|
||||||
|
@ -3273,24 +3287,25 @@
|
||||||
Disable all optional CPU mitigations. This
|
Disable all optional CPU mitigations. This
|
||||||
improves system performance, but it may also
|
improves system performance, but it may also
|
||||||
expose users to several CPU vulnerabilities.
|
expose users to several CPU vulnerabilities.
|
||||||
Equivalent to: nopti [X86,PPC]
|
Equivalent to: if nokaslr then kpti=0 [ARM64]
|
||||||
if nokaslr then kpti=0 [ARM64]
|
gather_data_sampling=off [X86]
|
||||||
nospectre_v1 [X86,PPC]
|
kvm.nx_huge_pages=off [X86]
|
||||||
nobp=0 [S390]
|
|
||||||
nospectre_v2 [X86,PPC,S390,ARM64]
|
|
||||||
spectre_v2_user=off [X86]
|
|
||||||
spec_store_bypass_disable=off [X86,PPC]
|
|
||||||
ssbd=force-off [ARM64]
|
|
||||||
nospectre_bhb [ARM64]
|
|
||||||
l1tf=off [X86]
|
l1tf=off [X86]
|
||||||
mds=off [X86]
|
mds=off [X86]
|
||||||
tsx_async_abort=off [X86]
|
mmio_stale_data=off [X86]
|
||||||
kvm.nx_huge_pages=off [X86]
|
|
||||||
srbds=off [X86,INTEL]
|
|
||||||
no_entry_flush [PPC]
|
no_entry_flush [PPC]
|
||||||
no_uaccess_flush [PPC]
|
no_uaccess_flush [PPC]
|
||||||
mmio_stale_data=off [X86]
|
nobp=0 [S390]
|
||||||
|
nopti [X86,PPC]
|
||||||
|
nospectre_bhb [ARM64]
|
||||||
|
nospectre_v1 [X86,PPC]
|
||||||
|
nospectre_v2 [X86,PPC,S390,ARM64]
|
||||||
retbleed=off [X86]
|
retbleed=off [X86]
|
||||||
|
spec_store_bypass_disable=off [X86,PPC]
|
||||||
|
spectre_v2_user=off [X86]
|
||||||
|
srbds=off [X86,INTEL]
|
||||||
|
ssbd=force-off [ARM64]
|
||||||
|
tsx_async_abort=off [X86]
|
||||||
|
|
||||||
Exceptions:
|
Exceptions:
|
||||||
This does not have any effect on
|
This does not have any effect on
|
||||||
|
|
|
@ -483,5 +483,6 @@
|
||||||
#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */
|
#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */
|
||||||
#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
|
#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
|
||||||
#define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
|
#define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
|
||||||
|
#define X86_BUG_GDS X86_BUG(30) /* CPU is affected by Gather Data Sampling */
|
||||||
|
|
||||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||||
|
|
|
@ -155,6 +155,15 @@
|
||||||
* Not susceptible to Post-Barrier
|
* Not susceptible to Post-Barrier
|
||||||
* Return Stack Buffer Predictions.
|
* Return Stack Buffer Predictions.
|
||||||
*/
|
*/
|
||||||
|
#define ARCH_CAP_GDS_CTRL BIT(25) /*
|
||||||
|
* CPU is vulnerable to Gather
|
||||||
|
* Data Sampling (GDS) and
|
||||||
|
* has controls for mitigation.
|
||||||
|
*/
|
||||||
|
#define ARCH_CAP_GDS_NO BIT(26) /*
|
||||||
|
* CPU is not vulnerable to Gather
|
||||||
|
* Data Sampling (GDS).
|
||||||
|
*/
|
||||||
|
|
||||||
#define ARCH_CAP_XAPIC_DISABLE BIT(21) /*
|
#define ARCH_CAP_XAPIC_DISABLE BIT(21) /*
|
||||||
* IA32_XAPIC_DISABLE_STATUS MSR
|
* IA32_XAPIC_DISABLE_STATUS MSR
|
||||||
|
@ -178,6 +187,8 @@
|
||||||
#define RNGDS_MITG_DIS BIT(0) /* SRBDS support */
|
#define RNGDS_MITG_DIS BIT(0) /* SRBDS support */
|
||||||
#define RTM_ALLOW BIT(1) /* TSX development mode */
|
#define RTM_ALLOW BIT(1) /* TSX development mode */
|
||||||
#define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */
|
#define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */
|
||||||
|
#define GDS_MITG_DIS BIT(4) /* Disable GDS mitigation */
|
||||||
|
#define GDS_MITG_LOCKED BIT(5) /* GDS mitigation locked */
|
||||||
|
|
||||||
#define MSR_IA32_SYSENTER_CS 0x00000174
|
#define MSR_IA32_SYSENTER_CS 0x00000174
|
||||||
#define MSR_IA32_SYSENTER_ESP 0x00000175
|
#define MSR_IA32_SYSENTER_ESP 0x00000175
|
||||||
|
|
|
@ -47,6 +47,7 @@ static void __init taa_select_mitigation(void);
|
||||||
static void __init mmio_select_mitigation(void);
|
static void __init mmio_select_mitigation(void);
|
||||||
static void __init srbds_select_mitigation(void);
|
static void __init srbds_select_mitigation(void);
|
||||||
static void __init l1d_flush_select_mitigation(void);
|
static void __init l1d_flush_select_mitigation(void);
|
||||||
|
static void __init gds_select_mitigation(void);
|
||||||
|
|
||||||
/* The base value of the SPEC_CTRL MSR without task-specific bits set */
|
/* The base value of the SPEC_CTRL MSR without task-specific bits set */
|
||||||
u64 x86_spec_ctrl_base;
|
u64 x86_spec_ctrl_base;
|
||||||
|
@ -160,6 +161,7 @@ void __init cpu_select_mitigations(void)
|
||||||
md_clear_select_mitigation();
|
md_clear_select_mitigation();
|
||||||
srbds_select_mitigation();
|
srbds_select_mitigation();
|
||||||
l1d_flush_select_mitigation();
|
l1d_flush_select_mitigation();
|
||||||
|
gds_select_mitigation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -645,6 +647,120 @@ static int __init l1d_flush_parse_cmdline(char *str)
|
||||||
}
|
}
|
||||||
early_param("l1d_flush", l1d_flush_parse_cmdline);
|
early_param("l1d_flush", l1d_flush_parse_cmdline);
|
||||||
|
|
||||||
|
#undef pr_fmt
|
||||||
|
#define pr_fmt(fmt) "GDS: " fmt
|
||||||
|
|
||||||
|
enum gds_mitigations {
|
||||||
|
GDS_MITIGATION_OFF,
|
||||||
|
GDS_MITIGATION_UCODE_NEEDED,
|
||||||
|
GDS_MITIGATION_FULL,
|
||||||
|
GDS_MITIGATION_FULL_LOCKED,
|
||||||
|
GDS_MITIGATION_HYPERVISOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FULL;
|
||||||
|
|
||||||
|
static const char * const gds_strings[] = {
|
||||||
|
[GDS_MITIGATION_OFF] = "Vulnerable",
|
||||||
|
[GDS_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode",
|
||||||
|
[GDS_MITIGATION_FULL] = "Mitigation: Microcode",
|
||||||
|
[GDS_MITIGATION_FULL_LOCKED] = "Mitigation: Microcode (locked)",
|
||||||
|
[GDS_MITIGATION_HYPERVISOR] = "Unknown: Dependent on hypervisor status",
|
||||||
|
};
|
||||||
|
|
||||||
|
void update_gds_msr(void)
|
||||||
|
{
|
||||||
|
u64 mcu_ctrl_after;
|
||||||
|
u64 mcu_ctrl;
|
||||||
|
|
||||||
|
switch (gds_mitigation) {
|
||||||
|
case GDS_MITIGATION_OFF:
|
||||||
|
rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
|
||||||
|
mcu_ctrl |= GDS_MITG_DIS;
|
||||||
|
break;
|
||||||
|
case GDS_MITIGATION_FULL_LOCKED:
|
||||||
|
/*
|
||||||
|
* The LOCKED state comes from the boot CPU. APs might not have
|
||||||
|
* the same state. Make sure the mitigation is enabled on all
|
||||||
|
* CPUs.
|
||||||
|
*/
|
||||||
|
case GDS_MITIGATION_FULL:
|
||||||
|
rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
|
||||||
|
mcu_ctrl &= ~GDS_MITG_DIS;
|
||||||
|
break;
|
||||||
|
case GDS_MITIGATION_UCODE_NEEDED:
|
||||||
|
case GDS_MITIGATION_HYPERVISOR:
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to make sure that the WRMSR value was not ignored. Writes to
|
||||||
|
* GDS_MITG_DIS will be ignored if this processor is locked but the boot
|
||||||
|
* processor was not.
|
||||||
|
*/
|
||||||
|
rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl_after);
|
||||||
|
WARN_ON_ONCE(mcu_ctrl != mcu_ctrl_after);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init gds_select_mitigation(void)
|
||||||
|
{
|
||||||
|
u64 mcu_ctrl;
|
||||||
|
|
||||||
|
if (!boot_cpu_has_bug(X86_BUG_GDS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
|
||||||
|
gds_mitigation = GDS_MITIGATION_HYPERVISOR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpu_mitigations_off())
|
||||||
|
gds_mitigation = GDS_MITIGATION_OFF;
|
||||||
|
/* Will verify below that mitigation _can_ be disabled */
|
||||||
|
|
||||||
|
/* No microcode */
|
||||||
|
if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) {
|
||||||
|
gds_mitigation = GDS_MITIGATION_UCODE_NEEDED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
|
||||||
|
if (mcu_ctrl & GDS_MITG_LOCKED) {
|
||||||
|
if (gds_mitigation == GDS_MITIGATION_OFF)
|
||||||
|
pr_warn("Mitigation locked. Disable failed.\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The mitigation is selected from the boot CPU. All other CPUs
|
||||||
|
* _should_ have the same state. If the boot CPU isn't locked
|
||||||
|
* but others are then update_gds_msr() will WARN() of the state
|
||||||
|
* mismatch. If the boot CPU is locked update_gds_msr() will
|
||||||
|
* ensure the other CPUs have the mitigation enabled.
|
||||||
|
*/
|
||||||
|
gds_mitigation = GDS_MITIGATION_FULL_LOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_gds_msr();
|
||||||
|
out:
|
||||||
|
pr_info("%s\n", gds_strings[gds_mitigation]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init gds_parse_cmdline(char *str)
|
||||||
|
{
|
||||||
|
if (!str)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!boot_cpu_has_bug(X86_BUG_GDS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!strcmp(str, "off"))
|
||||||
|
gds_mitigation = GDS_MITIGATION_OFF;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_param("gather_data_sampling", gds_parse_cmdline);
|
||||||
|
|
||||||
#undef pr_fmt
|
#undef pr_fmt
|
||||||
#define pr_fmt(fmt) "Spectre V1 : " fmt
|
#define pr_fmt(fmt) "Spectre V1 : " fmt
|
||||||
|
|
||||||
|
@ -2382,6 +2498,11 @@ static ssize_t retbleed_show_state(char *buf)
|
||||||
return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
|
return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t gds_show_state(char *buf)
|
||||||
|
{
|
||||||
|
return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
|
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf, unsigned int bug)
|
char *buf, unsigned int bug)
|
||||||
{
|
{
|
||||||
|
@ -2431,6 +2552,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
||||||
case X86_BUG_RETBLEED:
|
case X86_BUG_RETBLEED:
|
||||||
return retbleed_show_state(buf);
|
return retbleed_show_state(buf);
|
||||||
|
|
||||||
|
case X86_BUG_GDS:
|
||||||
|
return gds_show_state(buf);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2495,4 +2619,9 @@ ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, cha
|
||||||
{
|
{
|
||||||
return cpu_show_common(dev, attr, buf, X86_BUG_RETBLEED);
|
return cpu_show_common(dev, attr, buf, X86_BUG_RETBLEED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t cpu_show_gds(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return cpu_show_common(dev, attr, buf, X86_BUG_GDS);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1250,6 +1250,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
||||||
#define RETBLEED BIT(3)
|
#define RETBLEED BIT(3)
|
||||||
/* CPU is affected by SMT (cross-thread) return predictions */
|
/* CPU is affected by SMT (cross-thread) return predictions */
|
||||||
#define SMT_RSB BIT(4)
|
#define SMT_RSB BIT(4)
|
||||||
|
/* CPU is affected by GDS */
|
||||||
|
#define GDS BIT(5)
|
||||||
|
|
||||||
static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
|
static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
|
||||||
VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS),
|
VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS),
|
||||||
|
@ -1262,19 +1264,21 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
|
||||||
VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO),
|
VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO),
|
||||||
VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS),
|
VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS),
|
||||||
VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED),
|
||||||
VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED),
|
||||||
VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(CANNONLAKE_L, X86_STEPPING_ANY, RETBLEED),
|
VULNBL_INTEL_STEPPINGS(CANNONLAKE_L, X86_STEPPING_ANY, RETBLEED),
|
||||||
VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO),
|
VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO),
|
VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED),
|
||||||
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS),
|
||||||
|
VULNBL_INTEL_STEPPINGS(TIGERLAKE_L, X86_STEPPING_ANY, GDS),
|
||||||
|
VULNBL_INTEL_STEPPINGS(TIGERLAKE, X86_STEPPING_ANY, GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED),
|
||||||
VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED),
|
VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS),
|
||||||
VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPING_ANY, MMIO | MMIO_SBDS),
|
VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPING_ANY, MMIO | MMIO_SBDS),
|
||||||
VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO),
|
VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO),
|
||||||
VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS),
|
VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS),
|
||||||
|
@ -1406,6 +1410,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||||
if (cpu_matches(cpu_vuln_blacklist, SMT_RSB))
|
if (cpu_matches(cpu_vuln_blacklist, SMT_RSB))
|
||||||
setup_force_cpu_bug(X86_BUG_SMT_RSB);
|
setup_force_cpu_bug(X86_BUG_SMT_RSB);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if CPU is vulnerable to GDS. If running in a virtual machine on
|
||||||
|
* an affected processor, the VMM may have disabled the use of GATHER by
|
||||||
|
* disabling AVX2. The only way to do this in HW is to clear XCR0[2],
|
||||||
|
* which means that AVX will be disabled.
|
||||||
|
*/
|
||||||
|
if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) &&
|
||||||
|
boot_cpu_has(X86_FEATURE_AVX))
|
||||||
|
setup_force_cpu_bug(X86_BUG_GDS);
|
||||||
|
|
||||||
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
|
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1962,6 +1976,8 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
|
||||||
validate_apic_and_package_id(c);
|
validate_apic_and_package_id(c);
|
||||||
x86_spec_ctrl_setup_ap();
|
x86_spec_ctrl_setup_ap();
|
||||||
update_srbds_msr();
|
update_srbds_msr();
|
||||||
|
if (boot_cpu_has_bug(X86_BUG_GDS))
|
||||||
|
update_gds_msr();
|
||||||
|
|
||||||
tsx_ap_init();
|
tsx_ap_init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ void cpu_select_mitigations(void);
|
||||||
|
|
||||||
extern void x86_spec_ctrl_setup_ap(void);
|
extern void x86_spec_ctrl_setup_ap(void);
|
||||||
extern void update_srbds_msr(void);
|
extern void update_srbds_msr(void);
|
||||||
|
extern void update_gds_msr(void);
|
||||||
|
|
||||||
extern enum spectre_v2_mitigation spectre_v2_enabled;
|
extern enum spectre_v2_mitigation spectre_v2_enabled;
|
||||||
|
|
||||||
|
|
|
@ -577,6 +577,12 @@ ssize_t __weak cpu_show_retbleed(struct device *dev,
|
||||||
return sysfs_emit(buf, "Not affected\n");
|
return sysfs_emit(buf, "Not affected\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t __weak cpu_show_gds(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return sysfs_emit(buf, "Not affected\n");
|
||||||
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
|
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
|
||||||
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
|
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
|
||||||
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
|
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
|
||||||
|
@ -588,6 +594,7 @@ static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
|
||||||
static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
|
static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
|
||||||
static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
|
static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
|
||||||
static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
|
static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
|
||||||
|
static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
|
||||||
|
|
||||||
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
||||||
&dev_attr_meltdown.attr,
|
&dev_attr_meltdown.attr,
|
||||||
|
@ -601,6 +608,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
||||||
&dev_attr_srbds.attr,
|
&dev_attr_srbds.attr,
|
||||||
&dev_attr_mmio_stale_data.attr,
|
&dev_attr_mmio_stale_data.attr,
|
||||||
&dev_attr_retbleed.attr,
|
&dev_attr_retbleed.attr,
|
||||||
|
&dev_attr_gather_data_sampling.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue