x86/srso: Disable the mitigation on unaffected configurations

Message ID 20230813104517.3346-1-bp@alien8.de
State New
Headers
Series x86/srso: Disable the mitigation on unaffected configurations |

Commit Message

Borislav Petkov Aug. 13, 2023, 10:45 a.m. UTC
  From: "Borislav Petkov (AMD)" <bp@alien8.de>

Skip the srso cmd line parsing which is not needed on Zen1/2 with SMT
disabled and with the proper microcode applied (latter should be the
case anyway) as those are not affected.

Fixes: 5a15d8348881 ("x86/srso: Tie SBPB bit setting to microcode patch detection")
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
---
 arch/x86/kernel/cpu/bugs.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
  

Comments

Nikolay Borisov Aug. 14, 2023, 6:39 a.m. UTC | #1
On 13.08.23 г. 13:45 ч., Borislav Petkov wrote:
> From: "Borislav Petkov (AMD)" <bp@alien8.de>
> 
> Skip the srso cmd line parsing which is not needed on Zen1/2 with SMT
> disabled and with the proper microcode applied (latter should be the
> case anyway) as those are not affected.
> 
> Fixes: 5a15d8348881 ("x86/srso: Tie SBPB bit setting to microcode patch detection")
> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> ---
>   arch/x86/kernel/cpu/bugs.c | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index d02f73c5339d..8959a1b9fb80 100644
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -2418,8 +2418,10 @@ static void __init srso_select_mitigation(void)
>   		 * IBPB microcode has been applied.
>   		 */
>   		if ((boot_cpu_data.x86 < 0x19) &&
> -		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED)))
> +		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) {
>   			setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
> +			goto pred_cmd;

Actually can't you simply return, given that zen1/2 never have the SBPB 
flag set? Only zen3/4 with the updated microcode?


> +		}
>   	}
>   
>   	if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) {
> @@ -2696,6 +2698,9 @@ static ssize_t retbleed_show_state(char *buf)
>   
>   static ssize_t srso_show_state(char *buf)
>   {
> +	if (boot_cpu_has(X86_FEATURE_SRSO_NO))
> +		return sysfs_emit(buf, "Not affected\n");
> +
>   	return sysfs_emit(buf, "%s%s\n",
>   			  srso_strings[srso_mitigation],
>   			  (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));
  
Josh Poimboeuf Aug. 14, 2023, 8:08 p.m. UTC | #2
On Mon, Aug 14, 2023 at 09:39:11AM +0300, Nikolay Borisov wrote:
> 
> 
> On 13.08.23 г. 13:45 ч., Borislav Petkov wrote:
> > From: "Borislav Petkov (AMD)" <bp@alien8.de>
> > 
> > Skip the srso cmd line parsing which is not needed on Zen1/2 with SMT
> > disabled and with the proper microcode applied (latter should be the
> > case anyway) as those are not affected.
> > 
> > Fixes: 5a15d8348881 ("x86/srso: Tie SBPB bit setting to microcode patch detection")
> > Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> > ---
> >   arch/x86/kernel/cpu/bugs.c | 7 ++++++-
> >   1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> > index d02f73c5339d..8959a1b9fb80 100644
> > --- a/arch/x86/kernel/cpu/bugs.c
> > +++ b/arch/x86/kernel/cpu/bugs.c
> > @@ -2418,8 +2418,10 @@ static void __init srso_select_mitigation(void)
> >   		 * IBPB microcode has been applied.
> >   		 */
> >   		if ((boot_cpu_data.x86 < 0x19) &&
> > -		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED)))
> > +		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) {
> >   			setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
> > +			goto pred_cmd;
> 
> Actually can't you simply return, given that zen1/2 never have the SBPB flag
> set? Only zen3/4 with the updated microcode?

Tangentially, the 'cpu_smt_control == CPU_SMT_DISABLED' check is wrong,
as SMT could still get enabled at runtime and SRSO would be exposed.

Also is there a reason to re-use the hardware SRSO_NO bit rather than
clear the bug bit?  That seems cleaner, then you wouldn't need this
hack:

> > +	if (boot_cpu_has(X86_FEATURE_SRSO_NO))
> > +		return sysfs_emit(buf, "Not affected\n");
> > +
  
Josh Poimboeuf Aug. 14, 2023, 8:53 p.m. UTC | #3
On Mon, Aug 14, 2023 at 10:25:45PM +0200, Borislav Petkov wrote:
> On Mon, Aug 14, 2023 at 01:08:13PM -0700, Josh Poimboeuf wrote:
> > Tangentially, the 'cpu_smt_control == CPU_SMT_DISABLED' check is wrong,
> > as SMT could still get enabled at runtime and SRSO would be exposed.
> 
> Well, even if it gets exposed, I don't think we can safely enable the
> mitigation at runtime as alternatives have run already.

Right, I wasn't suggesting to enable the mitigation at runtime.  Rather,
enable the mitigation at boot time, if SMT is even possible.  That's
what we've done for other mitigations.  Better safe than sorry.

> I guess I could use CPU_SMT_FORCE_DISABLED here.

cpu_smt_possible() already does that.

> > Also is there a reason to re-use the hardware SRSO_NO bit
> 
> Not a hardware bit - this is set by software - it is only allocated in
> the CPUID leaf for easier interaction with guests.

2. ENUMERATION OF NEW CAPABILITIES
AMD is defining three new CPUID bits to assist with the enumeration of capabilities related to SRSO:
CPUID Fn8000_0021_EAX[29] (SRSO_NO) – If this bit is 1, it indicates the CPU is not subject to the SRSO
vulnerability.
CPUID Fn8000_0021_EAX[28] (IBPB_BRTYPE) – If this bit is 1, it indicates that MSR 49h (PRED_CMD) bit 0
(IBPB) flushes all branch type predictions from the CPU branch predictor.
CPUID Fn8000_0021_EAX[27] (SBPB)

> > rather than clear the bug bit? 
> 
> We don't clear the X86_BUGs. Ever. The logic is that if the CPU matches
> an affected CPU, that flag remains to show that it is potentially
> affected.

Hm, ok.  I thought that was the point of the vulnerabilities file.

> /sys/devices/system/cpu/vulnerabilities/ tells you what the actual state
> is.

Since technically the CPU is affected, I'm thinking it should say
"Mitigation: SMT disabled" or such, instead of "Not affected".

> > That seems cleaner, then you wouldn't need this hack:
> 
> Not a hack. This is just like the other "not affected" feature flags.

Hm?  You mean the *_NO ones that determine whether the BUG bits get set
in the first place?  How do they print "Not affected"?
  
Josh Poimboeuf Aug. 15, 2023, 7:58 p.m. UTC | #4
On Tue, Aug 15, 2023 at 11:57:24AM +0200, Borislav Petkov wrote:
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -2417,8 +2417,7 @@ static void __init srso_select_mitigation(void)
>  		 * Zen1/2 with SMT off aren't vulnerable after the right
>  		 * IBPB microcode has been applied.
>  		 */
> -		if ((boot_cpu_data.x86 < 0x19) &&
> -		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) {
> +		if (boot_cpu_data.x86 < 0x19 && !cpu_smt_possible()) {
>  			setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
>  			return;
>  		}
> @@ -2698,8 +2697,12 @@ static ssize_t retbleed_show_state(char *buf)
>  
>  static ssize_t srso_show_state(char *buf)
>  {
> -	if (boot_cpu_has(X86_FEATURE_SRSO_NO))
> -		return sysfs_emit(buf, "Not affected\n");
> +	if (boot_cpu_has(X86_FEATURE_SRSO_NO)) {
> +		if (sched_smt_active())
> +			return sysfs_emit(buf, "Not affected\n");
> +		else
> +			return sysfs_emit(buf, "Mitigation: SMT disabled\n");
> +	}

AFAICT, nowhere in the spec does it say the SRSO_NO bit won't get set by
future (fixed) HW.  In fact I'd expect it will, similar to other *_NO
flags.

Regardless, here SRSO_NO seems to mean two different things: "reported
safe by host (or HW)" and "not reported safe on Zen1/2 with SMT not
possible".

Also, in this code, the SRSO_NO+SMT combo doesn't seem logically
possible, as srso_show_state() only gets called if X86_BUG_SRSO is set,
which only happens if SRSO_NO is not set by the HW/host in the first
place.  So here, if boot_cpu_has(X86_FEATURE_SRSO_NO), it means SRSO_NO
was manually set by srso_select_mitigation(), and SMT can't possibly be
enabled.

Instead of piggybacking on SRSO_NO, which is confusing, why not just add
a new mitigation type, like:

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 6c04aef4b63b..c925b98f5a15 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -2343,6 +2343,7 @@ early_param("l1tf", l1tf_cmdline);
 enum srso_mitigation {
 	SRSO_MITIGATION_NONE,
 	SRSO_MITIGATION_MICROCODE,
+	SRSO_MITIGATION_SMT,
 	SRSO_MITIGATION_SAFE_RET,
 	SRSO_MITIGATION_IBPB,
 	SRSO_MITIGATION_IBPB_ON_VMEXIT,
@@ -2359,6 +2360,7 @@ enum srso_mitigation_cmd {
 static const char * const srso_strings[] = {
 	[SRSO_MITIGATION_NONE]           = "Vulnerable",
 	[SRSO_MITIGATION_MICROCODE]      = "Mitigation: microcode",
+	[SRSO_MITIGATION_SMT]		 = "Mitigation: SMT disabled",
 	[SRSO_MITIGATION_SAFE_RET]	 = "Mitigation: safe RET",
 	[SRSO_MITIGATION_IBPB]		 = "Mitigation: IBPB",
 	[SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only"
@@ -2407,19 +2409,15 @@ static void __init srso_select_mitigation(void)
 		pr_warn("IBPB-extending microcode not applied!\n");
 		pr_warn(SRSO_NOTICE);
 	} else {
-		/*
-		 * Enable the synthetic (even if in a real CPUID leaf)
-		 * flags for guests.
-		 */
+		/* Enable the synthetic flag, as HW doesn't set it. */
 		setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
 
 		/*
 		 * Zen1/2 with SMT off aren't vulnerable after the right
 		 * IBPB microcode has been applied.
 		 */
-		if ((boot_cpu_data.x86 < 0x19) &&
-		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) {
-			setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
+		if ((boot_cpu_data.x86 < 0x19) && !cpu_smt_possible()) {
+			srso_mitigation = SRSO_MITIGATION_SMT;
 			return;
 		}
 	}
@@ -2698,9 +2696,6 @@ static ssize_t retbleed_show_state(char *buf)
 
 static ssize_t srso_show_state(char *buf)
 {
-	if (boot_cpu_has(X86_FEATURE_SRSO_NO))
-		return sysfs_emit(buf, "Not affected\n");
-
 	return sysfs_emit(buf, "%s%s\n",
 			  srso_strings[srso_mitigation],
 			  (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));
  
Josh Poimboeuf Aug. 15, 2023, 9:27 p.m. UTC | #5
On Tue, Aug 15, 2023 at 10:17:53PM +0200, Borislav Petkov wrote:
> On Tue, Aug 15, 2023 at 12:58:31PM -0700, Josh Poimboeuf wrote:
> > AFAICT, nowhere in the spec does it say the SRSO_NO bit won't get set by
> > future (fixed) HW.  In fact I'd expect it will, similar to other *_NO
> > flags.
> 
> I'm pretty sure it won't.
> 
> SRSO_NO is synthesized by the hypervisor *software*. Nothing else.

Citation needed.

> It is there so that you don't check microcode version in the guest which
> is nearly impossible anyway.
> 
> > Regardless, here SRSO_NO seems to mean two different things: "reported
> > safe by host (or HW)" and "not reported safe on Zen1/2 with SMT not
> > possible".
> 
> Huh?

Can you clarify what doesn't make sense?

> > Also, in this code, the SRSO_NO+SMT combo doesn't seem logically
> > possible, as srso_show_state() only gets called if X86_BUG_SRSO is set,
> > which only happens if SRSO_NO is not set by the HW/host in the first
> > place.  So here, if boot_cpu_has(X86_FEATURE_SRSO_NO), it means SRSO_NO
> > was manually set by srso_select_mitigation(), and SMT can't possibly be
> > enabled.
> 
> Have you considered the case where Linux would set SRSO_NO when booting
> on future hardware, which is fixed?
> 
> There SRSO_NO and SMT will very much be possible.

How is that relevant to my comment?  The bug bit still wouldn't get set
and srso_show_state() still wouldn't be called.
  
Josh Poimboeuf Aug. 16, 2023, 6:29 p.m. UTC | #6
On Wed, Aug 16, 2023 at 07:35:31PM +0200, Borislav Petkov wrote:
> On Wed, Aug 16, 2023 at 09:07:57AM -0700, Josh Poimboeuf wrote:
> > In this case srso_show_state() is never called, so the following code
> > can't run:
> > 
> > +	if (boot_cpu_has(X86_FEATURE_SRSO_NO)) {
> > +		if (sched_smt_active())
> > +			return sysfs_emit(buf, "Not affected\n");
> 
> Ofc it can. If something has set X86_FEATURE_SRSO_NO early, before the
> bug bits detection happens, then you get:
> 
> $ cat /sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow
> Not affected

No, if the bug bit isn't set then that comes from cpu_show_common():

static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
			       char *buf, unsigned int bug)
{
	if (!boot_cpu_has_bug(bug))
		return sysfs_emit(buf, "Not affected\n");
  
Borislav Petkov Aug. 16, 2023, 6:58 p.m. UTC | #7
On Wed, Aug 16, 2023 at 11:29:40AM -0700, Josh Poimboeuf wrote:
> No, if the bug bit isn't set then that comes from cpu_show_common():
> 
> static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
> 			       char *buf, unsigned int bug)
> {
> 	if (!boot_cpu_has_bug(bug))
> 		return sysfs_emit(buf, "Not affected\n");

Bah, there was that thing too.

Ok, I'll zap the sched_smt_active() branch in srso_show_state() then.
  
Josh Poimboeuf Aug. 17, 2023, 2:54 p.m. UTC | #8
On Thu, Aug 17, 2023 at 11:07:27AM +0200, Borislav Petkov wrote:
> From: "Borislav Petkov (AMD)" <bp@alien8.de>
> Date: Tue, 15 Aug 2023 11:53:13 +0200
> Subject: [PATCH] x86/srso: Correct the mitigation status when SMT is disabled
> 
> Specify how is SRSO mitigated when SMT is disabled. Also, correct the
> SMT check for that.
> 
> Fixes: e9fbc47b818b ("x86/srso: Disable the mitigation on unaffected configurations")
> Suggested-by: Josh Poimboeuf <jpoimboe@kernel.org>
> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
> Link: https://lore.kernel.org/r/20230814200813.p5czl47zssuej7nv@treble

Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
  

Patch

diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index d02f73c5339d..8959a1b9fb80 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -2418,8 +2418,10 @@  static void __init srso_select_mitigation(void)
 		 * IBPB microcode has been applied.
 		 */
 		if ((boot_cpu_data.x86 < 0x19) &&
-		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED)))
+		    (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) {
 			setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
+			goto pred_cmd;
+		}
 	}
 
 	if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) {
@@ -2696,6 +2698,9 @@  static ssize_t retbleed_show_state(char *buf)
 
 static ssize_t srso_show_state(char *buf)
 {
+	if (boot_cpu_has(X86_FEATURE_SRSO_NO))
+		return sysfs_emit(buf, "Not affected\n");
+
 	return sysfs_emit(buf, "%s%s\n",
 			  srso_strings[srso_mitigation],
 			  (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));