Older CPUs beyond its Servicing period are not listed in the affected
processor list for MMIO Stale Data vulnerabilities. These CPUs currently
report "Not affected" in sysfs, which may not be correct.
Add support for "Unknown" reporting for such CPUs. Mitigation is not
deployed when the status is "Unknown".
"CPU is beyond its Servicing period" means these CPUs are beyond their
Servicing [1] period and have reached End of Servicing Updates (ESU) [2].
[1] Servicing: The process of providing functional and security
updates to Intel processors or platforms, utilizing the Intel Platform
Update (IPU) process or other similar mechanisms.
[2] End of Servicing Updates (ESU): ESU is the date at which Intel
will no longer provide Servicing, such as through IPU or other similar
update processes. ESU dates will typically be aligned to end of
quarter.
Suggested-by: Andrew Cooper <[email protected]>
Suggested-by: Tony Luck <[email protected]>
Fixes: 8d50cdf8b834 ("x86/speculation/mmio: Add sysfs reporting for Processor MMIO Stale Data")
Cc: [email protected]
Signed-off-by: Pawan Gupta <[email protected]>
---
CPU vulnerability is unknown if, hardware doesn't set the immunity bits
and CPU is not in the known-affected-list.
In order to report the unknown status, this patch sets the MMIO bug
for all Intel CPUs that don't have the hardware immunity bits set.
Based on the known-affected-list of CPUs, mitigation selection then
deploys the mitigation or sets the "Unknown" status; which is ugly.
I will appreciate suggestions to improve this.
Thanks,
Pawan
.../hw-vuln/processor_mmio_stale_data.rst | 3 +++
arch/x86/kernel/cpu/bugs.c | 11 +++++++-
arch/x86/kernel/cpu/common.c | 26 +++++++++++++------
arch/x86/kernel/cpu/cpu.h | 1 +
4 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
index 9393c50b5afc..55524e0798da 100644
--- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
+++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
@@ -230,6 +230,9 @@ The possible values in this file are:
* - 'Mitigation: Clear CPU buffers'
- The processor is vulnerable and the CPU buffer clearing mitigation is
enabled.
+ * - 'Unknown: CPU is beyond its Servicing period'
+ - The processor vulnerability status is unknown because it is
+ out of Servicing period. Mitigation is not attempted.
If the processor is vulnerable then the following information is appended to
the above information:
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 0dd04713434b..dd6e78d370bc 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -416,6 +416,7 @@ enum mmio_mitigations {
MMIO_MITIGATION_OFF,
MMIO_MITIGATION_UCODE_NEEDED,
MMIO_MITIGATION_VERW,
+ MMIO_MITIGATION_UNKNOWN,
};
/* Default mitigation for Processor MMIO Stale Data vulnerabilities */
@@ -426,12 +427,18 @@ static const char * const mmio_strings[] = {
[MMIO_MITIGATION_OFF] = "Vulnerable",
[MMIO_MITIGATION_UCODE_NEEDED] = "Vulnerable: Clear CPU buffers attempted, no microcode",
[MMIO_MITIGATION_VERW] = "Mitigation: Clear CPU buffers",
+ [MMIO_MITIGATION_UNKNOWN] = "Unknown: CPU is beyond its servicing period",
};
static void __init mmio_select_mitigation(void)
{
u64 ia32_cap;
+ if (mmio_stale_data_unknown()) {
+ mmio_mitigation = MMIO_MITIGATION_UNKNOWN;
+ return;
+ }
+
if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
cpu_mitigations_off()) {
mmio_mitigation = MMIO_MITIGATION_OFF;
@@ -1638,6 +1645,7 @@ void cpu_bugs_smt_update(void)
pr_warn_once(MMIO_MSG_SMT);
break;
case MMIO_MITIGATION_OFF:
+ case MMIO_MITIGATION_UNKNOWN:
break;
}
@@ -2235,7 +2243,8 @@ static ssize_t tsx_async_abort_show_state(char *buf)
static ssize_t mmio_stale_data_show_state(char *buf)
{
- if (mmio_mitigation == MMIO_MITIGATION_OFF)
+ if (mmio_mitigation == MMIO_MITIGATION_OFF ||
+ mmio_mitigation == MMIO_MITIGATION_UNKNOWN)
return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 736262a76a12..82088410870e 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1286,6 +1286,22 @@ static bool arch_cap_mmio_immune(u64 ia32_cap)
ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
}
+bool __init mmio_stale_data_unknown(void)
+{
+ u64 ia32_cap = x86_read_arch_cap_msr();
+
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+ return false;
+ /*
+ * CPU vulnerability is unknown when, hardware doesn't set the
+ * immunity bits and CPU is not in the known affected list.
+ */
+ if (!cpu_matches(cpu_vuln_blacklist, MMIO) &&
+ !arch_cap_mmio_immune(ia32_cap))
+ return true;
+ return false;
+}
+
static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
{
u64 ia32_cap = x86_read_arch_cap_msr();
@@ -1349,14 +1365,8 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
cpu_matches(cpu_vuln_blacklist, SRBDS | MMIO_SBDS))
setup_force_cpu_bug(X86_BUG_SRBDS);
- /*
- * Processor MMIO Stale Data bug enumeration
- *
- * Affected CPU list is generally enough to enumerate the vulnerability,
- * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
- * not want the guest to enumerate the bug.
- */
- if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
+ /* Processor MMIO Stale Data bug enumeration */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
!arch_cap_mmio_immune(ia32_cap))
setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 7c9b5893c30a..a2dbfc1bbc49 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -82,6 +82,7 @@ unsigned int aperfmperf_get_khz(int cpu);
extern void x86_spec_ctrl_setup_ap(void);
extern void update_srbds_msr(void);
+extern bool mmio_stale_data_unknown(void);
extern u64 x86_read_arch_cap_msr(void);
base-commit: 4a57a8400075bc5287c5c877702c68aeae2a033d
--
2.35.3
On Thu, Jul 14, 2022 at 06:30:19PM -0700, Pawan Gupta wrote:
> Older CPUs beyond its Servicing period are not listed in the affected
> processor list for MMIO Stale Data vulnerabilities. These CPUs currently
> report "Not affected" in sysfs, which may not be correct.
>
> Add support for "Unknown" reporting for such CPUs. Mitigation is not
> deployed when the status is "Unknown".
>
> "CPU is beyond its Servicing period" means these CPUs are beyond their
> Servicing [1] period and have reached End of Servicing Updates (ESU) [2].
>
> [1] Servicing: The process of providing functional and security
> updates to Intel processors or platforms, utilizing the Intel Platform
> Update (IPU) process or other similar mechanisms.
>
> [2] End of Servicing Updates (ESU): ESU is the date at which Intel
> will no longer provide Servicing, such as through IPU or other similar
> update processes. ESU dates will typically be aligned to end of
> quarter.
>
> Suggested-by: Andrew Cooper <[email protected]>
Ping! Is there any interest in fixing reporting for older processors?
On Thu, Jul 14, 2022 at 06:30:18PM -0700, Pawan Gupta wrote:
> Older CPUs beyond its Servicing period are not listed in the affected
> processor list for MMIO Stale Data vulnerabilities. These CPUs currently
> report "Not affected" in sysfs, which may not be correct.
>
> Add support for "Unknown" reporting for such CPUs. Mitigation is not
> deployed when the status is "Unknown".
>
> "CPU is beyond its Servicing period" means these CPUs are beyond their
> Servicing [1] period and have reached End of Servicing Updates (ESU) [2].
>
> [1] Servicing: The process of providing functional and security
> updates to Intel processors or platforms, utilizing the Intel Platform
> Update (IPU) process or other similar mechanisms.
>
> [2] End of Servicing Updates (ESU): ESU is the date at which Intel
> will no longer provide Servicing, such as through IPU or other similar
> update processes. ESU dates will typically be aligned to end of
> quarter.
The explanations of those things need to be...
> Suggested-by: Andrew Cooper <[email protected]>
> Suggested-by: Tony Luck <[email protected]>
> Fixes: 8d50cdf8b834 ("x86/speculation/mmio: Add sysfs reporting for Processor MMIO Stale Data")
> Cc: [email protected]
> Signed-off-by: Pawan Gupta <[email protected]>
> ---
> CPU vulnerability is unknown if, hardware doesn't set the immunity bits
> and CPU is not in the known-affected-list.
>
> In order to report the unknown status, this patch sets the MMIO bug
> for all Intel CPUs that don't have the hardware immunity bits set.
> Based on the known-affected-list of CPUs, mitigation selection then
> deploys the mitigation or sets the "Unknown" status; which is ugly.
>
> I will appreciate suggestions to improve this.
>
> Thanks,
> Pawan
>
> .../hw-vuln/processor_mmio_stale_data.rst | 3 +++
> arch/x86/kernel/cpu/bugs.c | 11 +++++++-
> arch/x86/kernel/cpu/common.c | 26 +++++++++++++------
> arch/x86/kernel/cpu/cpu.h | 1 +
> 4 files changed, 32 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> index 9393c50b5afc..55524e0798da 100644
> --- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> +++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> @@ -230,6 +230,9 @@ The possible values in this file are:
> * - 'Mitigation: Clear CPU buffers'
> - The processor is vulnerable and the CPU buffer clearing mitigation is
> enabled.
> + * - 'Unknown: CPU is beyond its Servicing period'
> + - The processor vulnerability status is unknown because it is
> + out of Servicing period. Mitigation is not attempted.
... here.
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 736262a76a12..82088410870e 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -1286,6 +1286,22 @@ static bool arch_cap_mmio_immune(u64 ia32_cap)
> ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
> }
>
> +bool __init mmio_stale_data_unknown(void)
This function need to go to ...cpu/intel.c
> +{
> + u64 ia32_cap = x86_read_arch_cap_msr();
> +
> + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
> + return false;
<---- newline here.
> + /*
> + * CPU vulnerability is unknown when, hardware doesn't set the
no comma after the "when"
> + * immunity bits and CPU is not in the known affected list.
> + */
> + if (!cpu_matches(cpu_vuln_blacklist, MMIO) &&
> + !arch_cap_mmio_immune(ia32_cap))
> + return true;
<---- newline here.
> + return false;
> +}
> +
> static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> {
> u64 ia32_cap = x86_read_arch_cap_msr();
> @@ -1349,14 +1365,8 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> cpu_matches(cpu_vuln_blacklist, SRBDS | MMIO_SBDS))
> setup_force_cpu_bug(X86_BUG_SRBDS);
>
> - /*
> - * Processor MMIO Stale Data bug enumeration
> - *
> - * Affected CPU list is generally enough to enumerate the vulnerability,
> - * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
> - * not want the guest to enumerate the bug.
> - */
> - if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> + /* Processor MMIO Stale Data bug enumeration */
> + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
Why is that vendor check here? We have the cpu_vuln_blacklist for a
reason.
> !arch_cap_mmio_immune(ia32_cap))
> setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On 7/14/22 18:30, Pawan Gupta wrote:
> Older CPUs beyond its Servicing period are not listed in the affected
> processor list for MMIO Stale Data vulnerabilities. These CPUs currently
> report "Not affected" in sysfs, which may not be correct.
I'd kinda like to remove the talk about the "servicing period" in this
patch. First, it's a moving target. CPUs can move in and out of their
servicing period as Intel changes its mind, or simply as time passes.
Intel could also totally choose to report a CPU as vulnerable *AND* have
it be outside its service period. Or, some good Samaritan community
member might be able to test a crusty old CPU and determine if it's
vulnerable.
> diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> index 9393c50b5afc..55524e0798da 100644
> --- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> +++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> @@ -230,6 +230,9 @@ The possible values in this file are:
> * - 'Mitigation: Clear CPU buffers'
> - The processor is vulnerable and the CPU buffer clearing mitigation is
> enabled.
> + * - 'Unknown: CPU is beyond its Servicing period'
> + - The processor vulnerability status is unknown because it is
> + out of Servicing period. Mitigation is not attempted.
Unknown: Processor vendor did not provide vulnerability status.
> If the processor is vulnerable then the following information is appended to
> the above information:
> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index 0dd04713434b..dd6e78d370bc 100644
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -416,6 +416,7 @@ enum mmio_mitigations {
> MMIO_MITIGATION_OFF,
> MMIO_MITIGATION_UCODE_NEEDED,
> MMIO_MITIGATION_VERW,
> + MMIO_MITIGATION_UNKNOWN,
> };
>
> /* Default mitigation for Processor MMIO Stale Data vulnerabilities */
> @@ -426,12 +427,18 @@ static const char * const mmio_strings[] = {
> [MMIO_MITIGATION_OFF] = "Vulnerable",
> [MMIO_MITIGATION_UCODE_NEEDED] = "Vulnerable: Clear CPU buffers attempted, no microcode",
> [MMIO_MITIGATION_VERW] = "Mitigation: Clear CPU buffers",
> + [MMIO_MITIGATION_UNKNOWN] = "Unknown: CPU is beyond its servicing period",
> };
Let's just say:
Unknown: no mitigations
or even just: "Unknown"
> static void __init mmio_select_mitigation(void)
> {
> u64 ia32_cap;
>
> + if (mmio_stale_data_unknown()) {
> + mmio_mitigation = MMIO_MITIGATION_UNKNOWN;
> + return;
> + }
> +
> if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
> cpu_mitigations_off()) {
> mmio_mitigation = MMIO_MITIGATION_OFF;
> @@ -1638,6 +1645,7 @@ void cpu_bugs_smt_update(void)
> pr_warn_once(MMIO_MSG_SMT);
> break;
> case MMIO_MITIGATION_OFF:
> + case MMIO_MITIGATION_UNKNOWN:
> break;
> }
>
> @@ -2235,7 +2243,8 @@ static ssize_t tsx_async_abort_show_state(char *buf)
>
> static ssize_t mmio_stale_data_show_state(char *buf)
> {
> - if (mmio_mitigation == MMIO_MITIGATION_OFF)
> + if (mmio_mitigation == MMIO_MITIGATION_OFF ||
> + mmio_mitigation == MMIO_MITIGATION_UNKNOWN)
> return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
>
> if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 736262a76a12..82088410870e 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -1286,6 +1286,22 @@ static bool arch_cap_mmio_immune(u64 ia32_cap)
> ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
> }
>
> +bool __init mmio_stale_data_unknown(void)
> +{
> + u64 ia32_cap = x86_read_arch_cap_msr();
> +
> + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
> + return false;
Let's say why Intel is the special snowflake. Maybe:
/*
* Intel does not document vulnerability information for old
* CPUs. This means that only Intel CPUs can have unknown
* vulnerability state.
*/
> + /*
> + * CPU vulnerability is unknown when, hardware doesn't set the
> + * immunity bits and CPU is not in the known affected list.
> + */
> + if (!cpu_matches(cpu_vuln_blacklist, MMIO) &&
> + !arch_cap_mmio_immune(ia32_cap))
> + return true;
> + return false;
> +}
> +
> static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> {
> u64 ia32_cap = x86_read_arch_cap_msr();
> @@ -1349,14 +1365,8 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> cpu_matches(cpu_vuln_blacklist, SRBDS | MMIO_SBDS))
> setup_force_cpu_bug(X86_BUG_SRBDS);
>
> - /*
> - * Processor MMIO Stale Data bug enumeration
> - *
> - * Affected CPU list is generally enough to enumerate the vulnerability,
> - * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
> - * not want the guest to enumerate the bug.
> - */
> - if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> + /* Processor MMIO Stale Data bug enumeration */
> + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
> !arch_cap_mmio_immune(ia32_cap))
> setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
Yeah, this is all looking a little clunky.
Maybe we just need a third state of cpu_has_bug() for all this and we
shouldn't try cramming it in the MMIO-specific code and diluting the
specificity of boot_cpu_has_bug().
Then the selection logic becomes simple:
if (!arch_cap_mmio_immune(ia32_cap))) {
if (cpu_matches(cpu_vuln_blacklist, MMIO))
setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
else if (x86_vendor == X86_VENDOR_INTEL)
setup_force_unknown_bug(X86_BUG_MMIO...);
}
... and then spit out the "Unknown" in the common code, just like the
treatment "Not affected" gets.
static ssize_t cpu_show_common(...)
{
if (!boot_cpu_has_bug(bug))
return sprintf(buf, "Not affected\n");
+
+ if (!boot_cpu_unknown_bug(bug))
+ return sprintf(buf, "Unknown\n");
Thoughts?
On Thu, Jul 28, 2022 at 02:00:13PM +0200, Borislav Petkov wrote:
> On Thu, Jul 14, 2022 at 06:30:18PM -0700, Pawan Gupta wrote:
> > Older CPUs beyond its Servicing period are not listed in the affected
> > processor list for MMIO Stale Data vulnerabilities. These CPUs currently
> > report "Not affected" in sysfs, which may not be correct.
> >
> > Add support for "Unknown" reporting for such CPUs. Mitigation is not
> > deployed when the status is "Unknown".
> >
> > "CPU is beyond its Servicing period" means these CPUs are beyond their
> > Servicing [1] period and have reached End of Servicing Updates (ESU) [2].
> >
> > [1] Servicing: The process of providing functional and security
> > updates to Intel processors or platforms, utilizing the Intel Platform
> > Update (IPU) process or other similar mechanisms.
> >
> > [2] End of Servicing Updates (ESU): ESU is the date at which Intel
> > will no longer provide Servicing, such as through IPU or other similar
> > update processes. ESU dates will typically be aligned to end of
> > quarter.
>
> The explanations of those things need to be...
>
> > Suggested-by: Andrew Cooper <[email protected]>
> > Suggested-by: Tony Luck <[email protected]>
> > Fixes: 8d50cdf8b834 ("x86/speculation/mmio: Add sysfs reporting for Processor MMIO Stale Data")
> > Cc: [email protected]
> > Signed-off-by: Pawan Gupta <[email protected]>
> > ---
> > CPU vulnerability is unknown if, hardware doesn't set the immunity bits
> > and CPU is not in the known-affected-list.
> >
> > In order to report the unknown status, this patch sets the MMIO bug
> > for all Intel CPUs that don't have the hardware immunity bits set.
> > Based on the known-affected-list of CPUs, mitigation selection then
> > deploys the mitigation or sets the "Unknown" status; which is ugly.
> >
> > I will appreciate suggestions to improve this.
> >
> > Thanks,
> > Pawan
> >
> > .../hw-vuln/processor_mmio_stale_data.rst | 3 +++
> > arch/x86/kernel/cpu/bugs.c | 11 +++++++-
> > arch/x86/kernel/cpu/common.c | 26 +++++++++++++------
> > arch/x86/kernel/cpu/cpu.h | 1 +
> > 4 files changed, 32 insertions(+), 9 deletions(-)
> >
> > diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> > index 9393c50b5afc..55524e0798da 100644
> > --- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> > +++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> > @@ -230,6 +230,9 @@ The possible values in this file are:
> > * - 'Mitigation: Clear CPU buffers'
> > - The processor is vulnerable and the CPU buffer clearing mitigation is
> > enabled.
> > + * - 'Unknown: CPU is beyond its Servicing period'
> > + - The processor vulnerability status is unknown because it is
> > + out of Servicing period. Mitigation is not attempted.
>
> ... here.
Sure, I will move it here.
> > diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> > index 736262a76a12..82088410870e 100644
> > --- a/arch/x86/kernel/cpu/common.c
> > +++ b/arch/x86/kernel/cpu/common.c
> > @@ -1286,6 +1286,22 @@ static bool arch_cap_mmio_immune(u64 ia32_cap)
> > ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
> > }
> >
> > +bool __init mmio_stale_data_unknown(void)
>
> This function need to go to ...cpu/intel.c
It will be big churn to move this function to ...cpu/intel.c.
cpu/intel.c is not compiled for !CONFIG_CPU_SUP_INTEL, and bugs.c
depends on this function. For bugs.c to compile there needs to be
another version of this function for !CONFIG_CPU_SUP_INTEL.
Secondly, this function relies on cpu_vuln_blacklist and
arch_cap_mmio_immune(), both are in cpu/common.c and defined static.
They would also need to made available in cpu/intel.c.
To keep things simple, can this stay in cpu/common.c? And if there is a
compelling reason, I am willing to make the required changes.
> > +{
> > + u64 ia32_cap = x86_read_arch_cap_msr();
> > +
> > + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
> > + return false;
>
> <---- newline here.
>
> > + /*
> > + * CPU vulnerability is unknown when, hardware doesn't set the
>
> no comma after the "when"
>
> > + * immunity bits and CPU is not in the known affected list.
> > + */
> > + if (!cpu_matches(cpu_vuln_blacklist, MMIO) &&
> > + !arch_cap_mmio_immune(ia32_cap))
> > + return true;
>
> <---- newline here.
Will do this, and above changes.
> > + return false;
> > +}
> > +
> > static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> > {
> > u64 ia32_cap = x86_read_arch_cap_msr();
> > @@ -1349,14 +1365,8 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> > cpu_matches(cpu_vuln_blacklist, SRBDS | MMIO_SBDS))
> > setup_force_cpu_bug(X86_BUG_SRBDS);
> >
> > - /*
> > - * Processor MMIO Stale Data bug enumeration
> > - *
> > - * Affected CPU list is generally enough to enumerate the vulnerability,
> > - * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
> > - * not want the guest to enumerate the bug.
> > - */
> > - if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> > + /* Processor MMIO Stale Data bug enumeration */
> > + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
>
> Why is that vendor check here? We have the cpu_vuln_blacklist for a
> reason.
cpu_vuln_blacklist only has in-support MMIO vulnerable CPUs.
There is no easy way to report unknown status for older CPUs. This
patch sets the MMIO bug for all Intel CPUs that don't have the hardware
immunity bits set.
Later, mmio_select_mitigation() deploys the mitigation or sets the
"Unknown" status based on the known-affected-list of CPUs i.e.
cpu_vuln_blacklist.
The vendor check is required, otherwise MMIO bug will be set for
non-Intel CPUs also.
Thanks,
Pawan
From: Pawan Gupta
> Sent: 29 July 2022 03:29
>
> On Thu, Jul 28, 2022 at 02:00:13PM +0200, Borislav Petkov wrote:
> > On Thu, Jul 14, 2022 at 06:30:18PM -0700, Pawan Gupta wrote:
> > > Older CPUs beyond its Servicing period are not listed in the affected
> > > processor list for MMIO Stale Data vulnerabilities. These CPUs currently
> > > report "Not affected" in sysfs, which may not be correct.
I looked this up....
The mitigations seem to rely on unprivileged code not being able
to do MMIO accesses.
That isn't true, device drivers can mmap PCIe addresses directly
into user program address space.
While unlikely, there is no reason this can't be supported for
non-root processes.
So if the underlying hardware doesn't correctly validate the
byte enables then stale data can be read.
It has to be said that I can't actually imagine getting anything
useful unless you have co-operating processes using it as a
security bypass side channel.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
On Thu, Jul 28, 2022 at 07:28:51PM -0700, Pawan Gupta wrote:
> To keep things simple, can this stay in cpu/common.c?
I know, right?
The gullible maintainer should simply take your half-baked patch so that
you can check off that box and then he can clean it up later.
So you've been doing this kernel development thing for a while. Didn't
it get obvious by now that we don't do half-baked?!
See if this works:
---
diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
index 9393c50b5afc..14cd3c6ddec6 100644
--- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
+++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
@@ -230,6 +230,21 @@ The possible values in this file are:
* - 'Mitigation: Clear CPU buffers'
- The processor is vulnerable and the CPU buffer clearing mitigation is
enabled.
+ * - 'Unknown: CPU is beyond its servicing period'
+ - The processor vulnerability status is unknown because it is
+ out of Servicing period. Mitigation is not attempted.
+
+
+Definitions:
+------------
+
+Servicing period: The process of providing functional and security
+updates to Intel processors or platforms, utilizing the Intel Platform
+Update (IPU) process or other similar mechanisms.
+
+End of Servicing Updates (ESU): ESU is the date at which Intel will no
+longer provide Servicing, such as through IPU or other similar update
+processes. ESU dates will typically be aligned to end of quarter.
If the processor is vulnerable then the following information is appended to
the above information:
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index ea34cc31b047..fe66e94d7b86 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -154,6 +154,7 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
} while (0)
#define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit)
+#define setup_clear_cpu_bug(bit) setup_clear_cpu_cap(bit)
#if defined(__clang__) && !defined(CONFIG_CC_HAS_ASM_GOTO)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 5fe7f6c8a7a4..130cb46ecaf9 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -454,7 +454,8 @@
#define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
-#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
-#define X86_BUG_RETBLEED X86_BUG(26) /* CPU is affected by RETBleed */
+#define X86_BUG_MMIO_UNKNOWN X86_BUG(25) /* CPU is too old and its MMIO Stale Data status is unknown */
+#define X86_BUG_MMIO_STALE_DATA X86_BUG(26) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
+#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 6454bc767f0f..a83d1c4265ae 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -433,7 +433,8 @@ static void __init mmio_select_mitigation(void)
u64 ia32_cap;
if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
- cpu_mitigations_off()) {
+ boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
+ cpu_mitigations_off()) {
mmio_mitigation = MMIO_MITIGATION_OFF;
return;
}
@@ -2247,6 +2248,9 @@ static ssize_t tsx_async_abort_show_state(char *buf)
static ssize_t mmio_stale_data_show_state(char *buf)
{
+ if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+ return sysfs_emit(buf, "Unknown: CPU is beyond its servicing period\n");
+
if (mmio_mitigation == MMIO_MITIGATION_OFF)
return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
@@ -2378,6 +2382,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
return srbds_show_state(buf);
case X86_BUG_MMIO_STALE_DATA:
+ case X86_BUG_MMIO_UNKNOWN:
return mmio_stale_data_show_state(buf);
case X86_BUG_RETBLEED:
@@ -2437,7 +2442,10 @@ ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *
ssize_t cpu_show_mmio_stale_data(struct device *dev, struct device_attribute *attr, char *buf)
{
- return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
+ if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+ return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_UNKNOWN);
+ else
+ return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
}
ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, char *buf)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 736262a76a12..fb3e8576a3b4 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1356,9 +1356,13 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
* but for virtualization case check for ARCH_CAP MSR bits also, VMM may
* not want the guest to enumerate the bug.
*/
- if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
- !arch_cap_mmio_immune(ia32_cap))
- setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+ if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN)) {
+ if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
+ !arch_cap_mmio_immune(ia32_cap)) {
+ setup_clear_cpu_bug(X86_BUG_MMIO_UNKNOWN);
+ setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+ }
+ }
if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 663f6e6dd288..5b2508adc38a 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -372,6 +372,10 @@ static void early_init_intel(struct cpuinfo_x86 *c)
static void bsp_init_intel(struct cpuinfo_x86 *c)
{
resctrl_cpu_detect(c);
+
+ /* Set on older crap */
+ if (c->x86_model < INTEL_FAM6_IVYBRIDGE)
+ setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
}
#ifdef CONFIG_X86_32
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On Fri, Jul 29, 2022 at 10:40:20AM +0000, David Laight wrote:
> From: Pawan Gupta
> > Sent: 29 July 2022 03:29
> >
> > On Thu, Jul 28, 2022 at 02:00:13PM +0200, Borislav Petkov wrote:
> > > On Thu, Jul 14, 2022 at 06:30:18PM -0700, Pawan Gupta wrote:
> > > > Older CPUs beyond its Servicing period are not listed in the affected
> > > > processor list for MMIO Stale Data vulnerabilities. These CPUs currently
> > > > report "Not affected" in sysfs, which may not be correct.
>
> I looked this up....
>
> The mitigations seem to rely on unprivileged code not being able
> to do MMIO accesses.
> That isn't true, device drivers can mmap PCIe addresses directly
> into user program address space.
> While unlikely, there is no reason this can't be supported for
> non-root processes.
Agree. Would it be fair to assume that processes that get direct
hardware access are trusted?
On Thu, Jul 28, 2022 at 12:08:39PM -0700, Dave Hansen wrote:
> On 7/14/22 18:30, Pawan Gupta wrote:
> > Older CPUs beyond its Servicing period are not listed in the affected
> > processor list for MMIO Stale Data vulnerabilities. These CPUs currently
> > report "Not affected" in sysfs, which may not be correct.
>
> I'd kinda like to remove the talk about the "servicing period" in this
> patch. First, it's a moving target. CPUs can move in and out of their
> servicing period as Intel changes its mind, or simply as time passes.
>
> Intel could also totally choose to report a CPU as vulnerable *AND* have
> it be outside its service period. Or, some good Samaritan community
> member might be able to test a crusty old CPU and determine if it's
> vulnerable.
>
> > diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> > index 9393c50b5afc..55524e0798da 100644
> > --- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> > +++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> > @@ -230,6 +230,9 @@ The possible values in this file are:
> > * - 'Mitigation: Clear CPU buffers'
> > - The processor is vulnerable and the CPU buffer clearing mitigation is
> > enabled.
> > + * - 'Unknown: CPU is beyond its Servicing period'
> > + - The processor vulnerability status is unknown because it is
> > + out of Servicing period. Mitigation is not attempted.
>
> Unknown: Processor vendor did not provide vulnerability status.
>
> > If the processor is vulnerable then the following information is appended to
> > the above information:
> > diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> > index 0dd04713434b..dd6e78d370bc 100644
> > --- a/arch/x86/kernel/cpu/bugs.c
> > +++ b/arch/x86/kernel/cpu/bugs.c
> > @@ -416,6 +416,7 @@ enum mmio_mitigations {
> > MMIO_MITIGATION_OFF,
> > MMIO_MITIGATION_UCODE_NEEDED,
> > MMIO_MITIGATION_VERW,
> > + MMIO_MITIGATION_UNKNOWN,
> > };
> >
> > /* Default mitigation for Processor MMIO Stale Data vulnerabilities */
> > @@ -426,12 +427,18 @@ static const char * const mmio_strings[] = {
> > [MMIO_MITIGATION_OFF] = "Vulnerable",
> > [MMIO_MITIGATION_UCODE_NEEDED] = "Vulnerable: Clear CPU buffers attempted, no microcode",
> > [MMIO_MITIGATION_VERW] = "Mitigation: Clear CPU buffers",
> > + [MMIO_MITIGATION_UNKNOWN] = "Unknown: CPU is beyond its servicing period",
> > };
>
> Let's just say:
>
> Unknown: no mitigations
>
> or even just: "Unknown"
>
> > static void __init mmio_select_mitigation(void)
> > {
> > u64 ia32_cap;
> >
> > + if (mmio_stale_data_unknown()) {
> > + mmio_mitigation = MMIO_MITIGATION_UNKNOWN;
> > + return;
> > + }
> > +
> > if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
> > cpu_mitigations_off()) {
> > mmio_mitigation = MMIO_MITIGATION_OFF;
> > @@ -1638,6 +1645,7 @@ void cpu_bugs_smt_update(void)
> > pr_warn_once(MMIO_MSG_SMT);
> > break;
> > case MMIO_MITIGATION_OFF:
> > + case MMIO_MITIGATION_UNKNOWN:
> > break;
> > }
> >
> > @@ -2235,7 +2243,8 @@ static ssize_t tsx_async_abort_show_state(char *buf)
> >
> > static ssize_t mmio_stale_data_show_state(char *buf)
> > {
> > - if (mmio_mitigation == MMIO_MITIGATION_OFF)
> > + if (mmio_mitigation == MMIO_MITIGATION_OFF ||
> > + mmio_mitigation == MMIO_MITIGATION_UNKNOWN)
> > return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
> >
> > if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
> > diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> > index 736262a76a12..82088410870e 100644
> > --- a/arch/x86/kernel/cpu/common.c
> > +++ b/arch/x86/kernel/cpu/common.c
> > @@ -1286,6 +1286,22 @@ static bool arch_cap_mmio_immune(u64 ia32_cap)
> > ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
> > }
> >
> > +bool __init mmio_stale_data_unknown(void)
> > +{
> > + u64 ia32_cap = x86_read_arch_cap_msr();
> > +
> > + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
> > + return false;
>
> Let's say why Intel is the special snowflake. Maybe:
>
> /*
> * Intel does not document vulnerability information for old
> * CPUs. This means that only Intel CPUs can have unknown
> * vulnerability state.
> */
>
> > + /*
> > + * CPU vulnerability is unknown when, hardware doesn't set the
> > + * immunity bits and CPU is not in the known affected list.
> > + */
> > + if (!cpu_matches(cpu_vuln_blacklist, MMIO) &&
> > + !arch_cap_mmio_immune(ia32_cap))
> > + return true;
> > + return false;
> > +}
> > +
> > static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> > {
> > u64 ia32_cap = x86_read_arch_cap_msr();
> > @@ -1349,14 +1365,8 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> > cpu_matches(cpu_vuln_blacklist, SRBDS | MMIO_SBDS))
> > setup_force_cpu_bug(X86_BUG_SRBDS);
> >
> > - /*
> > - * Processor MMIO Stale Data bug enumeration
> > - *
> > - * Affected CPU list is generally enough to enumerate the vulnerability,
> > - * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
> > - * not want the guest to enumerate the bug.
> > - */
> > - if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> > + /* Processor MMIO Stale Data bug enumeration */
> > + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
> > !arch_cap_mmio_immune(ia32_cap))
> > setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
>
> Yeah, this is all looking a little clunky.
>
> Maybe we just need a third state of cpu_has_bug() for all this and we
> shouldn't try cramming it in the MMIO-specific code and diluting the
> specificity of boot_cpu_has_bug().
>
> Then the selection logic becomes simple:
>
> if (!arch_cap_mmio_immune(ia32_cap))) {
> if (cpu_matches(cpu_vuln_blacklist, MMIO))
> setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
> else if (x86_vendor == X86_VENDOR_INTEL)
> setup_force_unknown_bug(X86_BUG_MMIO...);
> }
>
> ... and then spit out the "Unknown" in the common code, just like the
> treatment "Not affected" gets.
>
> static ssize_t cpu_show_common(...)
> {
> if (!boot_cpu_has_bug(bug))
> return sprintf(buf, "Not affected\n");
> +
> + if (!boot_cpu_unknown_bug(bug))
> + return sprintf(buf, "Unknown\n");
>
> Thoughts?
Sounds good. Similar to this Borislav suggested to add
X86_BUG_MMIO_UNKNOWN. I will see if I can combine both approaches.
On Fri, Jul 29, 2022 at 04:05:29PM +0200, Borislav Petkov wrote:
> On Thu, Jul 28, 2022 at 07:28:51PM -0700, Pawan Gupta wrote:
> > To keep things simple, can this stay in cpu/common.c?
>
> I know, right?
>
> The gullible maintainer should simply take your half-baked patch so that
> you can check off that box and then he can clean it up later.
I am sorry if it felt like that, its really not my intention.
I did also say:
"And if there is a compelling reason, I am willing to make the
required changes."
I was genuinely curious about why not to use cpu/common.c for mmio.
cpu/common.c is heavily used for bugs infrastructure. It already has the
affected tables, bug enumerations and helper functions for previous
bugs. Maybe it needs a cleanup as a whole.
> See if this works:
Thanks for this.
> ---
> diff --git a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> index 9393c50b5afc..14cd3c6ddec6 100644
> --- a/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> +++ b/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
> @@ -230,6 +230,21 @@ The possible values in this file are:
> * - 'Mitigation: Clear CPU buffers'
> - The processor is vulnerable and the CPU buffer clearing mitigation is
> enabled.
> + * - 'Unknown: CPU is beyond its servicing period'
> + - The processor vulnerability status is unknown because it is
> + out of Servicing period. Mitigation is not attempted.
> +
> +
> +Definitions:
> +------------
> +
> +Servicing period: The process of providing functional and security
> +updates to Intel processors or platforms, utilizing the Intel Platform
> +Update (IPU) process or other similar mechanisms.
> +
> +End of Servicing Updates (ESU): ESU is the date at which Intel will no
> +longer provide Servicing, such as through IPU or other similar update
> +processes. ESU dates will typically be aligned to end of quarter.
>
> If the processor is vulnerable then the following information is appended to
> the above information:
> diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
> index ea34cc31b047..fe66e94d7b86 100644
> --- a/arch/x86/include/asm/cpufeature.h
> +++ b/arch/x86/include/asm/cpufeature.h
> @@ -154,6 +154,7 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
> } while (0)
>
> #define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit)
> +#define setup_clear_cpu_bug(bit) setup_clear_cpu_cap(bit)
>
> #if defined(__clang__) && !defined(CONFIG_CC_HAS_ASM_GOTO)
>
> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> index 5fe7f6c8a7a4..130cb46ecaf9 100644
> --- a/arch/x86/include/asm/cpufeatures.h
> +++ b/arch/x86/include/asm/cpufeatures.h
> @@ -454,7 +454,8 @@
> #define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
> #define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
> #define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
> -#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
> -#define X86_BUG_RETBLEED X86_BUG(26) /* CPU is affected by RETBleed */
> +#define X86_BUG_MMIO_UNKNOWN X86_BUG(25) /* CPU is too old and its MMIO Stale Data status is unknown */
> +#define X86_BUG_MMIO_STALE_DATA X86_BUG(26) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
> +#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */
>
> #endif /* _ASM_X86_CPUFEATURES_H */
> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index 6454bc767f0f..a83d1c4265ae 100644
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -433,7 +433,8 @@ static void __init mmio_select_mitigation(void)
> u64 ia32_cap;
>
> if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
> - cpu_mitigations_off()) {
> + boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
> + cpu_mitigations_off()) {
> mmio_mitigation = MMIO_MITIGATION_OFF;
> return;
> }
> @@ -2247,6 +2248,9 @@ static ssize_t tsx_async_abort_show_state(char *buf)
>
> static ssize_t mmio_stale_data_show_state(char *buf)
> {
> + if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
> + return sysfs_emit(buf, "Unknown: CPU is beyond its servicing period\n");
> +
> if (mmio_mitigation == MMIO_MITIGATION_OFF)
> return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
>
> @@ -2378,6 +2382,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
> return srbds_show_state(buf);
>
> case X86_BUG_MMIO_STALE_DATA:
> + case X86_BUG_MMIO_UNKNOWN:
> return mmio_stale_data_show_state(buf);
>
> case X86_BUG_RETBLEED:
> @@ -2437,7 +2442,10 @@ ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *
>
> ssize_t cpu_show_mmio_stale_data(struct device *dev, struct device_attribute *attr, char *buf)
> {
> - return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
> + if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
> + return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_UNKNOWN);
> + else
> + return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
> }
>
> ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, char *buf)
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 736262a76a12..fb3e8576a3b4 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -1356,9 +1356,13 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
> * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
> * not want the guest to enumerate the bug.
> */
> - if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> - !arch_cap_mmio_immune(ia32_cap))
> - setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
> + if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN)) {
This should be !boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN). Otherwise
X86_BUG_MMIO_STALE_DATA will not be set on affected systems.
> + if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> + !arch_cap_mmio_immune(ia32_cap)) {
> + setup_clear_cpu_bug(X86_BUG_MMIO_UNKNOWN);
Clearing X86_BUG_MMIO_UNKNOWN wont be required then.
> + setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
> + }
> + }
Does this look okay:
- if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
- !arch_cap_mmio_immune(ia32_cap))
- setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+ if (!boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN)) {
+ if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
+ !arch_cap_mmio_immune(ia32_cap)) {
+ setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+ }
+ }
> if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
> if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
> diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
> index 663f6e6dd288..5b2508adc38a 100644
> --- a/arch/x86/kernel/cpu/intel.c
> +++ b/arch/x86/kernel/cpu/intel.c
> @@ -372,6 +372,10 @@ static void early_init_intel(struct cpuinfo_x86 *c)
> static void bsp_init_intel(struct cpuinfo_x86 *c)
> {
> resctrl_cpu_detect(c);
> +
> + /* Set on older crap */
> + if (c->x86_model < INTEL_FAM6_IVYBRIDGE)
> + setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
Thanks for suggesting this approach.
On 7/29/22 10:59, Pawan Gupta wrote:
>> + if (!boot_cpu_unknown_bug(bug))
>> + return sprintf(buf, "Unknown\n");
>>
>> Thoughts?
> Sounds good. Similar to this Borislav suggested to add
> X86_BUG_MMIO_UNKNOWN. I will see if I can combine both approaches.
I'd say Borislav's is better if there is going to be a small number of
"unknown" things in total. Mine might be better if we expect a *bunch*
of them.
In other words, I'm rooting for Borislav's.
On Fri, Jul 29, 2022 at 10:36:09AM -0700, Pawan Gupta wrote:
> Does this look okay:
>
> - if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> - !arch_cap_mmio_immune(ia32_cap))
> - setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
> + if (!boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN)) {
> + if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> + !arch_cap_mmio_immune(ia32_cap)) {
> + setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
> + }
> + }
Yeah, I had initially X86_BUG_MMIO_UNKNOWN set unconditionally on all.
Then I thought I should set it only on older but as dhansen said, Intel
is going in and out of servicing period so we better set it on all
initially and then clear it when the CPU is not in the vuln blacklist.
>
> > if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
> > if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
> > diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
> > index 663f6e6dd288..5b2508adc38a 100644
> > --- a/arch/x86/kernel/cpu/intel.c
> > +++ b/arch/x86/kernel/cpu/intel.c
> > @@ -372,6 +372,10 @@ static void early_init_intel(struct cpuinfo_x86 *c)
> > static void bsp_init_intel(struct cpuinfo_x86 *c)
> > {
> > resctrl_cpu_detect(c);
> > +
> > + /* Set on older crap */
> > + if (c->x86_model < INTEL_FAM6_IVYBRIDGE)
i.e., remove this check.
> > + setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
>
> Thanks for suggesting this approach.
You're welcome. I'm assuming you're gonna finish it or should I?
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On Fri, Jul 29, 2022 at 10:30:38PM +0200, Borislav Petkov wrote:
> On Fri, Jul 29, 2022 at 10:36:09AM -0700, Pawan Gupta wrote:
> > Does this look okay:
> >
> > - if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> > - !arch_cap_mmio_immune(ia32_cap))
> > - setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
> > + if (!boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN)) {
> > + if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
> > + !arch_cap_mmio_immune(ia32_cap)) {
> > + setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
> > + }
> > + }
>
> Yeah, I had initially X86_BUG_MMIO_UNKNOWN set unconditionally on all.
>
> Then I thought I should set it only on older but as dhansen said, Intel
> is going in and out of servicing period so we better set it on all
> initially and then clear it when the CPU is not in the vuln blacklist.
Setting all to "unknown" initially can lead to some CPUs incorrectly
reporting "Unknown".
Let me see if there is a way to distinguish between 4. and 5. below:
CPU category X86_BUG_MMIO_STALE_DATA X86_BUG_MMIO_UNKNOWN
-----------------------------------------------------------------------------------------------
1. Known affected (in cpu list) 1 0
2. CPUs with HW immunity (MMIO_NO=1) 0 0
3. Other vendors 0 0
4. Older Intel CPUs 0 1
5. Not affected current CPUs (but MMIO_NO=0) 0 ?
> > > if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
> > > if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
> > > diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
> > > index 663f6e6dd288..5b2508adc38a 100644
> > > --- a/arch/x86/kernel/cpu/intel.c
> > > +++ b/arch/x86/kernel/cpu/intel.c
> > > @@ -372,6 +372,10 @@ static void early_init_intel(struct cpuinfo_x86 *c)
> > > static void bsp_init_intel(struct cpuinfo_x86 *c)
> > > {
> > > resctrl_cpu_detect(c);
> > > +
> > > + /* Set on older crap */
> > > + if (c->x86_model < INTEL_FAM6_IVYBRIDGE)
>
> i.e., remove this check.
This check actually solves the above problem, but consider it gone.
> > > + setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
> >
> > Thanks for suggesting this approach.
>
> You're welcome. I'm assuming you're gonna finish it or should I?
I will finish it, working on it.
On Fri, Jul 29, 2022 at 02:46:27PM -0700, Pawan Gupta wrote:
> Let me see if there is a way to distinguish between 4. and 5. below:
>
> CPU category X86_BUG_MMIO_STALE_DATA X86_BUG_MMIO_UNKNOWN
> -----------------------------------------------------------------------------------------------
> 1. Known affected (in cpu list) 1 0
> 2. CPUs with HW immunity (MMIO_NO=1) 0 0
> 3. Other vendors 0 0
> 4. Older Intel CPUs 0 1
> 5. Not affected current CPUs (but MMIO_NO=0) 0 ?
Not affected current CPUs should be arch_cap_mmio_immune() == true, no?
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On 7/29/22 14:46, Pawan Gupta wrote:
> Let me see if there is a way to distinguish between 4. and 5. below:
>
> CPU category X86_BUG_MMIO_STALE_DATA X86_BUG_MMIO_UNKNOWN
> -----------------------------------------------------------------------------------------------
> 1. Known affected (in cpu list) 1 0
> 2. CPUs with HW immunity (MMIO_NO=1) 0 0
> 3. Other vendors 0 0
> 4. Older Intel CPUs 0 1
> 5. Not affected current CPUs (but MMIO_NO=0) 0 ?
This seems like something we would need to go back to our colleagues to
figure out. Basically, at the time of publishing the
X86_BUG_MMIO_STALE_DATA papers, what was considered "older"?
In other words, we need the folks at Intel that did this good work to
_show_ their work (at least part of it).
On Fri, Jul 29, 2022 at 03:54:58PM -0700, Dave Hansen wrote:
> On 7/29/22 14:46, Pawan Gupta wrote:
> > Let me see if there is a way to distinguish between 4. and 5. below:
> >
> > CPU category X86_BUG_MMIO_STALE_DATA X86_BUG_MMIO_UNKNOWN
> > -----------------------------------------------------------------------------------------------
> > 1. Known affected (in cpu list) 1 0
> > 2. CPUs with HW immunity (MMIO_NO=1) 0 0
> > 3. Other vendors 0 0
> > 4. Older Intel CPUs 0 1
> > 5. Not affected current CPUs (but MMIO_NO=0) 0 ?
>
> This seems like something we would need to go back to our colleagues to
> figure out. Basically, at the time of publishing the
> X86_BUG_MMIO_STALE_DATA papers, what was considered "older"?
>
> In other words, we need the folks at Intel that did this good work to
> _show_ their work (at least part of it).
https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
Click to the 2022 tab. The MMIO affected/not-affected status is there
(you'll need to use the horizontal scroll to shift over to see those
columns).
This table lists all the CPUs that were not "older".
Any CPU not on that list is out of servicing period.
-Tony
On 7/29/22 16:07, Tony Luck wrote:
> https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
>
> Click to the 2022 tab. The MMIO affected/not-affected status is there
> (you'll need to use the horizontal scroll to shift over to see those
> columns).
>
> This table lists all the CPUs that were not "older".
>
> Any CPU not on that list is out of servicing period.
Perfect! Thanks, Tony!
On Sat, Jul 30, 2022 at 12:02:34AM +0200, Borislav Petkov wrote:
> On Fri, Jul 29, 2022 at 02:46:27PM -0700, Pawan Gupta wrote:
> > Let me see if there is a way to distinguish between 4. and 5. below:
> >
> > CPU category X86_BUG_MMIO_STALE_DATA X86_BUG_MMIO_UNKNOWN
> > -----------------------------------------------------------------------------------------------
> > 1. Known affected (in cpu list) 1 0
> > 2. CPUs with HW immunity (MMIO_NO=1) 0 0
> > 3. Other vendors 0 0
> > 4. Older Intel CPUs 0 1
> > 5. Not affected current CPUs (but MMIO_NO=0) 0 ?
>
> Not affected current CPUs should be arch_cap_mmio_immune() == true, no?
That would be true in most cases, with some exceptions like systems
that did not update the microcode.
On Fri, Jul 29, 2022 at 04:07:36PM -0700, Tony Luck wrote:
> On Fri, Jul 29, 2022 at 03:54:58PM -0700, Dave Hansen wrote:
> > On 7/29/22 14:46, Pawan Gupta wrote:
> > > Let me see if there is a way to distinguish between 4. and 5. below:
> > >
> > > CPU category X86_BUG_MMIO_STALE_DATA X86_BUG_MMIO_UNKNOWN
> > > -----------------------------------------------------------------------------------------------
> > > 1. Known affected (in cpu list) 1 0
> > > 2. CPUs with HW immunity (MMIO_NO=1) 0 0
> > > 3. Other vendors 0 0
> > > 4. Older Intel CPUs 0 1
> > > 5. Not affected current CPUs (but MMIO_NO=0) 0 ?
> >
> > This seems like something we would need to go back to our colleagues to
> > figure out. Basically, at the time of publishing the
> > X86_BUG_MMIO_STALE_DATA papers, what was considered "older"?
> >
> > In other words, we need the folks at Intel that did this good work to
> > _show_ their work (at least part of it).
>
> https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
>
> Click to the 2022 tab. The MMIO affected/not-affected status is there
> (you'll need to use the horizontal scroll to shift over to see those
> columns).
>
> This table lists all the CPUs that were not "older".
>
> Any CPU not on that list is out of servicing period.
I thought about this option, this will require CPUs to be added to
whitelist too. If the maintainers wont hate it, I will go this route.