mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
Mitigate Gather Data Sampling issue
* Add Base GDS mitigation * Support GDS_NO under KVM * Fix a documentation typo -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEV76QKkVc4xCGURexaDWVMHDJkrAFAmTJh5YACgkQaDWVMHDJ krAzAw/8DzjhAYEa7a1AodCBMNg8uNOPnLNoRPPNhaN5Iw6W3zXYDBDKT9PyjAIx RoIM0aHx/oY9nCpK441o25oCWAAyzk6E5/+q9hMa7B4aHUGKqiDUC6L9dC8UiiSN yvoBv4g7F81QnmyazwYI64S6vnbr4Cqe7K/mvVqQ/vbJiugD25zY8mflRV9YAuMk Oe7Ff/mCA+I/kqyKhJE3cf3qNhZ61FsFI886fOSvIE7g4THKqo5eGPpIQxR4mXiU Ri2JWffTaeHr2m0sAfFeLH4VTZxfAgBkNQUEWeG6f2kDGTEKibXFRsU4+zxjn3gl xug+9jfnKN1ceKyNlVeJJZKAfr2TiyUtrlSE5d+subIRKKBaAGgnCQDasaFAluzd aZkOYz30PCebhN+KTrR84FySHCaxnev04jqdtVGAQEDbTvyNagFUdZFGhWijJShV l2l4A0gFSYJmPfPVuuAwOJnnZtA1sRH9oz/Sny3+z9BKloZh+Nc/+Cu9zC8SLjaU BF3Qv2gU9HKTJ+MSy2JrGS52cONfpO5ngFHoOMilZ1KBHrfSb1eiy32PDT+vK60Y PFEmI8SWl7bmrO1snVUCfGaHBsHJSu5KMqwBGmM4xSRzJpyvRe493xC7+nFvqNLY vFOFc4jGeusOXgiLPpfGduppkTGcM7sy75UMLwTSLcQbDK99mus= =ZAPY -----END PGP SIGNATURE----- Merge tag 'gds-for-linus-2023-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86/gds fixes from Dave Hansen: "Mitigate Gather Data Sampling issue: - Add Base GDS mitigation - Support GDS_NO under KVM - Fix a documentation typo" * tag 'gds-for-linus-2023-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: Documentation/x86: Fix backwards on/off logic about YMM support KVM: Add GDS_NO support to KVM x86/speculation: Add Kconfig option for GDS x86/speculation: Add force option to GDS mitigation x86/speculation: Add Gather Data Sampling mitigation
This commit is contained in:
commit
64094e7e31
@ -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
|
||||||
|
109
Documentation/admin-guide/hw-vuln/gather_data_sampling.rst
Normal file
109
Documentation/admin-guide/hw-vuln/gather_data_sampling.rst
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
.. 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 gather_data_sampling="force" or
|
||||||
|
"clearcpuid=avx" on the kernel command-line.
|
||||||
|
|
||||||
|
If used, these options will disable AVX use by turning off 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. 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
|
||||||
|
------------------------
|
||||||
|
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: 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
|
||||||
|
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.
|
@ -20,3 +20,4 @@ are configurable at compile, boot or run time.
|
|||||||
processor_mmio_stale_data.rst
|
processor_mmio_stale_data.rst
|
||||||
cross-thread-rsb.rst
|
cross-thread-rsb.rst
|
||||||
srso
|
srso
|
||||||
|
gather_data_sampling.rst
|
||||||
|
@ -1623,6 +1623,26 @@
|
|||||||
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. 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.
|
||||||
|
|
||||||
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 +3293,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
|
||||||
|
@ -2610,6 +2610,25 @@ config SLS
|
|||||||
against straight line speculation. The kernel image might be slightly
|
against straight line speculation. The kernel image might be slightly
|
||||||
larger.
|
larger.
|
||||||
|
|
||||||
|
config GDS_FORCE_MITIGATION
|
||||||
|
bool "Force GDS Mitigation"
|
||||||
|
depends on CPU_SUP_INTEL
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Gather Data Sampling (GDS) is a hardware vulnerability which allows
|
||||||
|
unprivileged speculative access to data which was previously stored in
|
||||||
|
vector registers.
|
||||||
|
|
||||||
|
This option is equivalent to setting gather_data_sampling=force on the
|
||||||
|
command line. The microcode mitigation is used if present, otherwise
|
||||||
|
AVX is disabled as a mitigation. On affected systems that are missing
|
||||||
|
the microcode any userspace code that unconditionally uses AVX will
|
||||||
|
break with this option set.
|
||||||
|
|
||||||
|
Setting this option on systems not vulnerable to GDS has no effect.
|
||||||
|
|
||||||
|
If in doubt, say N.
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config ARCH_HAS_ADD_PAGES
|
config ARCH_HAS_ADD_PAGES
|
||||||
|
@ -491,6 +491,7 @@
|
|||||||
#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 */
|
||||||
|
|
||||||
/* BUG word 2 */
|
/* BUG word 2 */
|
||||||
#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */
|
#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */
|
||||||
|
@ -156,6 +156,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
|
||||||
@ -179,6 +188,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
|
||||||
|
@ -48,6 +48,7 @@ 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 srso_select_mitigation(void);
|
static void __init srso_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;
|
||||||
@ -165,6 +166,7 @@ void __init cpu_select_mitigations(void)
|
|||||||
srbds_select_mitigation();
|
srbds_select_mitigation();
|
||||||
l1d_flush_select_mitigation();
|
l1d_flush_select_mitigation();
|
||||||
srso_select_mitigation();
|
srso_select_mitigation();
|
||||||
|
gds_select_mitigation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -650,6 +652,149 @@ 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_FORCE,
|
||||||
|
GDS_MITIGATION_FULL,
|
||||||
|
GDS_MITIGATION_FULL_LOCKED,
|
||||||
|
GDS_MITIGATION_HYPERVISOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_GDS_FORCE_MITIGATION)
|
||||||
|
static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FORCE;
|
||||||
|
#else
|
||||||
|
static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool gds_ucode_mitigated(void)
|
||||||
|
{
|
||||||
|
return (gds_mitigation == GDS_MITIGATION_FULL ||
|
||||||
|
gds_mitigation == GDS_MITIGATION_FULL_LOCKED);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(gds_ucode_mitigated);
|
||||||
|
|
||||||
|
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_FORCE:
|
||||||
|
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)) {
|
||||||
|
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)
|
||||||
|
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;
|
||||||
|
else if (!strcmp(str, "force"))
|
||||||
|
gds_mitigation = GDS_MITIGATION_FORCE;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@ -2556,6 +2701,11 @@ static ssize_t srso_show_state(char *buf)
|
|||||||
(cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));
|
(cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
@ -2608,6 +2758,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
|||||||
case X86_BUG_SRSO:
|
case X86_BUG_SRSO:
|
||||||
return srso_show_state(buf);
|
return srso_show_state(buf);
|
||||||
|
|
||||||
|
case X86_BUG_GDS:
|
||||||
|
return gds_show_state(buf);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2677,4 +2830,9 @@ ssize_t cpu_show_spec_rstack_overflow(struct device *dev, struct device_attribut
|
|||||||
{
|
{
|
||||||
return cpu_show_common(dev, attr, buf, X86_BUG_SRSO);
|
return cpu_show_common(dev, attr, buf, X86_BUG_SRSO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -1252,6 +1252,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
|||||||
#define SMT_RSB BIT(4)
|
#define SMT_RSB BIT(4)
|
||||||
/* CPU is affected by SRSO */
|
/* CPU is affected by SRSO */
|
||||||
#define SRSO BIT(5)
|
#define SRSO BIT(5)
|
||||||
|
/* CPU is affected by GDS */
|
||||||
|
#define GDS BIT(6)
|
||||||
|
|
||||||
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),
|
||||||
@ -1264,19 +1266,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),
|
||||||
@ -1414,6 +1418,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
|||||||
setup_force_cpu_bug(X86_BUG_SRSO);
|
setup_force_cpu_bug(X86_BUG_SRSO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
@ -1970,6 +1984,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;
|
||||||
|
|
||||||
|
@ -314,6 +314,8 @@ u64 __read_mostly host_xcr0;
|
|||||||
|
|
||||||
static struct kmem_cache *x86_emulator_cache;
|
static struct kmem_cache *x86_emulator_cache;
|
||||||
|
|
||||||
|
extern bool gds_ucode_mitigated(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When called, it means the previous get/set msr reached an invalid msr.
|
* When called, it means the previous get/set msr reached an invalid msr.
|
||||||
* Return true if we want to ignore/silent this failed msr access.
|
* Return true if we want to ignore/silent this failed msr access.
|
||||||
@ -1616,7 +1618,7 @@ static bool kvm_is_immutable_feature_msr(u32 msr)
|
|||||||
ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \
|
ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \
|
||||||
ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
|
ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
|
||||||
ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
|
ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
|
||||||
ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO)
|
ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO)
|
||||||
|
|
||||||
static u64 kvm_get_arch_capabilities(void)
|
static u64 kvm_get_arch_capabilities(void)
|
||||||
{
|
{
|
||||||
@ -1673,6 +1675,9 @@ static u64 kvm_get_arch_capabilities(void)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!boot_cpu_has_bug(X86_BUG_GDS) || gds_ucode_mitigated())
|
||||||
|
data |= ARCH_CAP_GDS_NO;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,6 +583,12 @@ ssize_t __weak cpu_show_spec_rstack_overflow(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);
|
||||||
@ -595,6 +601,7 @@ 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(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
|
static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, 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,
|
||||||
@ -609,6 +616,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
|||||||
&dev_attr_mmio_stale_data.attr,
|
&dev_attr_mmio_stale_data.attr,
|
||||||
&dev_attr_retbleed.attr,
|
&dev_attr_retbleed.attr,
|
||||||
&dev_attr_spec_rstack_overflow.attr,
|
&dev_attr_spec_rstack_overflow.attr,
|
||||||
|
&dev_attr_gather_data_sampling.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user