[PATCH v2 5/5] x86/cpu: Don't transiently clear the boot CPU's capabilities
Ihor Solodrai <[email protected]>
| Newsgroups | gmane.linux.kernel,gmane.linux.kernel.bpf,gmane.linux.kernel.mm |
|---|---|
| Message-ID | <[email protected]> |
On the boot CPU identify_cpu() runs from arch_cpu_finalize_init(),
with interrupts enabled and before alternatives are patched. So
cpu_feature_enabled() still evaluates against boot_cpu_data.
identify_cpu() rebuilds c->x86_capability from scratch: the reset
zeroes the array and the CPUID rescan fills it in again. An interrupt
delivered in that window finds X86_FEATURE_LA57 clear in
boot_cpu_data, so pgtable_l5_enabled() is false and KASAN checks a
5-level address against the 4-level addressability limit. The result
is a bogus "wild-memory-access" report, and under kasan_multi_shot a
report storm that wedges the boot.
The boot CPU has already been scanned by early_identify_cpu(), with
interrupts disabled, and its capabilities cannot have changed
since. Reset only the CPUs which have not been scanned yet.
32-bit gets the same treatment: the window is the same, and any
feature bit evaluated from interrupt context while it is open reads as
clear. Its no-CPUID cpuid_level default now comes from
early_identify_cpu(), and nothing writes cpuid_level again unless
CPUID is there to be read.
The window is as old as identify_cpu() rebuilding the capabilities.
Commit 39b9552281ab ("x86/mm: Optimize boot-time paging mode switching
cost") merely let KASAN notice it by making pgtable_l5_enabled() read
the feature bit. So no Fixes: tag.
Closes: https://lore.kernel.org/bpf/[email protected]/
Signed-off-by: Ihor Solodrai <[email protected]>
---
arch/x86/kernel/cpu/common.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 671a430994ca..e0c70a2510af 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1988,8 +1988,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
c->loops_per_jiffy = loops_per_jiffy;
- init_cpu_info(c);
-
if (!cpuid_feature())
identify_cpu_without_cpuid(c);
@@ -2174,6 +2172,7 @@ void identify_secondary_cpu(unsigned int cpu)
*c = boot_cpu_data;
c->cpu_index = cpu;
+ init_cpu_info(c);
identify_cpu(c);
x86_spec_ctrl_setup_ap();
update_srbds_msr();
--
2.55.0