mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-30 00:03:27 -04:00
Merge tag 'x86-urgent-2026-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
- Fix an early boot crash in AMD SEV-SNP guests, caused by incorrect
FSGSBASE init ordering (Nikunj A Dadhania)
- Remove X86_CR4_FRED from the CR4 pinned bits mask, to fix a race
window during the bootup of SEV-{ES,SNP} or TDX guests, which can
crash them if they trigger exceptions in that window (Borislav
Petkov)
- Fix early boot failures on SEV-ES/SNP guests, due to incorrect early
GHCB access (Nikunj A Dadhania)
- Add clarifying comment to the CRn pinning logic, to avoid future
confusion & bugs (Peter Zijlstra)
* tag 'x86-urgent-2026-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/cpu: Add comment clarifying CRn pinning
x86/fred: Fix early boot failures on SEV-ES/SNP guests
x86/cpu: Remove X86_CR4_FRED from the CR4 pinned bits mask
x86/cpu: Enable FSGSBASE early in cpu_init_exception_handling()
This commit is contained in:
@@ -121,6 +121,9 @@ noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state)
|
||||
|
||||
WARN_ON(!irqs_disabled());
|
||||
|
||||
if (!sev_cfg.ghcbs_initialized)
|
||||
return boot_ghcb;
|
||||
|
||||
data = this_cpu_read(runtime_data);
|
||||
ghcb = &data->ghcb_page;
|
||||
|
||||
@@ -164,6 +167,9 @@ noinstr void __sev_put_ghcb(struct ghcb_state *state)
|
||||
|
||||
WARN_ON(!irqs_disabled());
|
||||
|
||||
if (!sev_cfg.ghcbs_initialized)
|
||||
return;
|
||||
|
||||
data = this_cpu_read(runtime_data);
|
||||
ghcb = &data->ghcb_page;
|
||||
|
||||
|
||||
@@ -177,6 +177,16 @@ static noinstr void fred_extint(struct pt_regs *regs)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||
noinstr void exc_vmm_communication(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
if (user_mode(regs))
|
||||
return user_exc_vmm_communication(regs, error_code);
|
||||
else
|
||||
return kernel_exc_vmm_communication(regs, error_code);
|
||||
}
|
||||
#endif
|
||||
|
||||
static noinstr void fred_hwexc(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
/* Optimize for #PF. That's the only exception which matters performance wise */
|
||||
@@ -207,6 +217,10 @@ static noinstr void fred_hwexc(struct pt_regs *regs, unsigned long error_code)
|
||||
#ifdef CONFIG_X86_CET
|
||||
case X86_TRAP_CP: return exc_control_protection(regs, error_code);
|
||||
#endif
|
||||
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||
case X86_TRAP_VC: return exc_vmm_communication(regs, error_code);
|
||||
#endif
|
||||
|
||||
default: return fred_bad_type(regs, error_code);
|
||||
}
|
||||
|
||||
|
||||
@@ -433,7 +433,20 @@ static __always_inline void setup_lass(struct cpuinfo_x86 *c)
|
||||
|
||||
/* These bits should not change their value after CPU init is finished. */
|
||||
static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP |
|
||||
X86_CR4_FSGSBASE | X86_CR4_CET | X86_CR4_FRED;
|
||||
X86_CR4_FSGSBASE | X86_CR4_CET;
|
||||
|
||||
/*
|
||||
* The CR pinning protects against ROP on the 'mov %reg, %CRn' instruction(s).
|
||||
* Since you can ROP directly to these instructions (barring shadow stack),
|
||||
* any protection must follow immediately and unconditionally after that.
|
||||
*
|
||||
* Specifically, the CR[04] write functions below will have the value
|
||||
* validation controlled by the @cr_pinning static_branch which is
|
||||
* __ro_after_init, just like the cr4_pinned_bits value.
|
||||
*
|
||||
* Once set, an attacker will have to defeat page-tables to get around these
|
||||
* restrictions. Which is a much bigger ask than 'simple' ROP.
|
||||
*/
|
||||
static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning);
|
||||
static unsigned long cr4_pinned_bits __ro_after_init;
|
||||
|
||||
@@ -2050,12 +2063,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
|
||||
setup_umip(c);
|
||||
setup_lass(c);
|
||||
|
||||
/* Enable FSGSBASE instructions if available. */
|
||||
if (cpu_has(c, X86_FEATURE_FSGSBASE)) {
|
||||
cr4_set_bits(X86_CR4_FSGSBASE);
|
||||
elf_hwcap2 |= HWCAP2_FSGSBASE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The vendor-specific functions might have changed features.
|
||||
* Now we do "generic changes."
|
||||
@@ -2416,6 +2423,18 @@ void cpu_init_exception_handling(bool boot_cpu)
|
||||
/* GHCB needs to be setup to handle #VC. */
|
||||
setup_ghcb();
|
||||
|
||||
/*
|
||||
* On CPUs with FSGSBASE support, paranoid_entry() uses
|
||||
* ALTERNATIVE-patched RDGSBASE/WRGSBASE instructions. Secondary CPUs
|
||||
* boot after alternatives are patched globally, so early exceptions
|
||||
* execute patched code that depends on FSGSBASE. Enable the feature
|
||||
* before any exceptions occur.
|
||||
*/
|
||||
if (cpu_feature_enabled(X86_FEATURE_FSGSBASE)) {
|
||||
cr4_set_bits(X86_CR4_FSGSBASE);
|
||||
elf_hwcap2 |= HWCAP2_FSGSBASE;
|
||||
}
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_FRED)) {
|
||||
/* The boot CPU has enabled FRED during early boot */
|
||||
if (!boot_cpu)
|
||||
|
||||
Reference in New Issue
Block a user