lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241119-force-cpu-bug-v1-1-2aa31c6c1ccf@google.com>
Date: Tue, 19 Nov 2024 18:43:57 +0000
From: Brendan Jackman <jackmanb@...gle.com>
To: Jonathan Corbet <corbet@....net>, Thomas Gleixner <tglx@...utronix.de>, Ingo Molnar <mingo@...hat.com>, 
	Borislav Petkov <bp@...en8.de>, Dave Hansen <dave.hansen@...ux.intel.com>, x86@...nel.org, 
	"H. Peter Anvin" <hpa@...or.com>, Peter Zijlstra <peterz@...radead.org>
Cc: linux-doc@...r.kernel.org, linux-kernel@...r.kernel.org, 
	Brendan Jackman <jackmanb@...gle.com>
Subject: [PATCH] x86/bugs: Add force_cpu_bug= cmdline param

Sometimes it can be very useful to run CPU vulnerability mitigations on
systems where they aren't known to mitigate any real-world
vulnerabilities. This can be handy for mundane reasons like "I wanna
debug this on the machine that quickly", but also for research reasons:
while some mitigations are focussed on individual vulns and uarches,
others are fairly general, and it's strategically useful to have an idea
how they'd perform on systems where we don't currently need them.

As evidence for this being useful, a flag specifically for Retbleed was
added in commit 5c9a92dec323 ("x86/bugs: Add retbleed=force").

It's a bit unfortunate that we have to do this by bug instead of by
mitigation. However, we don't have clear identifiers for the mitigations
that we do, so I don't think it's practical to do better here than "you
can pretend you're on a vulnerable CPU - now go and read the docs for
the per-vuln cmdline params to figure out how to run the mitigation you
want".

Being an early_param() means we get to do this before identify_cpu() and
cpu_select_mitigations(). But it's possible there's still other types of
bugs that get setup earlier and might miss this override...

I've only tested this by booting a QEMU guest and checking /proc/cpuinfo.

Signed-off-by: Brendan Jackman <jackmanb@...gle.com>
---
 Documentation/admin-guide/kernel-parameters.txt |  6 ++++
 arch/x86/kernel/cpu/common.c                    | 40 +++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index d401577b5a6ace87d250d9b1cc200691c6a0ed4e..260267a6d555076735fda09d171c918e6412b6e1 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1559,6 +1559,12 @@
 	floppy=		[HW]
 			See Documentation/admin-guide/blockdev/floppy.rst.
 
+	force_cpu_bug=	[X86,EARLY]
+			Force the kernel to assume the CPU is affected by the
+			given bug, regardless of its built-in information about
+			individual models.  Comma-separated list of the names of
+			vulnerabilities that would appear in /proc/cpuinfo.
+
 	forcepae	[X86-32]
 			Forcefully enable Physical Address Extension (PAE).
 			Many Pentium M systems disable PAE but may have a
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index f43bb974fc66d7b21ad52c64da22694ccc274187..b86b0200a5bf0de692f07d4ffef50ba7c360975d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1318,6 +1318,10 @@ static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr)
 	return cpu_matches(cpu_vuln_blacklist, RFDS);
 }
 
+/*
+ * This sets up what we _really_ think the CPU has. The user might override this
+ * later via force_cpu_bug.
+ */
 static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 {
 	u64 x86_arch_cap_msr = x86_read_arch_cap_msr();
@@ -1462,6 +1466,42 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 	setup_force_cpu_bug(X86_BUG_L1TF);
 }
 
+static int __init force_cpu_bug_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	while (str) {
+		char *next = strchr(str, ',');
+		int i;
+
+		if (next) {
+			*next = 0;
+			next++;
+		}
+
+		/*
+		 * Linear search because there aren't many bugs (well, at least
+		 * not for the definition of "many" that is relevant here...).
+		 *
+		 * Some configs have no gaps so we could stop at the first NULL,
+		 * but it isn't worth the ifdeffery.
+		 */
+		for (i = 0; i < ARRAY_SIZE(x86_bug_flags); i++) {
+			if (x86_bug_flags[i] && !strcmp(str, x86_bug_flags[i])) {
+				setup_force_cpu_bug(X86_BUG(i));
+				goto found;
+			}
+		}
+		pr_err("Ignoring unknown force_cpu_bug= option (%s).", str);
+found:
+		str = next;
+	}
+
+	return 0;
+}
+early_param("force_cpu_bug", force_cpu_bug_parse_cmdline);
+
 /*
  * The NOPL instruction is supposed to exist on all CPUs of family >= 6;
  * unfortunately, that's not true in practice because of early VIA

---
base-commit: adc218676eef25575469234709c2d87185ca223a
change-id: 20241119-force-cpu-bug-94a08ab0239f

Best regards,
-- 
Brendan Jackman <jackmanb@...gle.com>


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ