x86/spec-ctrl: Mitigate Gather Data Sampling

This is part of XSA-435 / CVE-2022-40982

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2023-08-08 15:19:49 +01:00
1 parent 9f585f59d9
commit 56d690efd3
2 files changed
+167 -1

No files matched your search

+9 -1
View File
@@ -2335,7 +2335,7 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`).
> {msr-sc,rsb,md-clear,ibpb-entry}=<bool>|{pv,hvm}=<bool>, > {msr-sc,rsb,md-clear,ibpb-entry}=<bool>|{pv,hvm}=<bool>,
> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd, > bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd,
> eager-fpu,l1d-flush,branch-harden,srb-lock, > eager-fpu,l1d-flush,branch-harden,srb-lock,
> unpriv-mmio}=<bool> ]` > unpriv-mmio,gds-mit}=<bool> ]`
Controls for speculative execution sidechannel mitigations. By default, Xen Controls for speculative execution sidechannel mitigations. By default, Xen
will pick the most appropriate mitigations based on compiled in support, will pick the most appropriate mitigations based on compiled in support,
@@ -2449,6 +2449,14 @@ and/or `SRBDS_CTRL` functionality available in the Intel May 2022 microcode
release to mitigate cross-domain leakage of data via the MMIO Stale Data release to mitigate cross-domain leakage of data via the MMIO Stale Data
vulnerabilities. vulnerabilities.
On all hardware, the `gds-mit=` option can be used to force or prevent Xen
from mitigating the GDS (Gather Data Sampling) vulnerability. By default, Xen
will mitigate GDS on hardware believed to be vulnerable. On hardware
supporting GDS_CTRL (requires the August 2023 microcode), and where firmware
has elected not to lock the configuration, Xen will use GDS_CTRL to mitigate
GDS with. Otherwise, Xen will mitigate by disabling AVX, which blocks the use
of the AVX2 Gather instructions.
### sync_console ### sync_console
> `= <boolean>` > `= <boolean>`
+158
View File
@@ -66,6 +66,7 @@ static bool __initdata cpu_has_bug_mds; /* Any other M{LP,SB,FB}DS combination.
static int8_t __initdata opt_srb_lock = -1; static int8_t __initdata opt_srb_lock = -1;
static bool __initdata opt_unpriv_mmio; static bool __initdata opt_unpriv_mmio;
static bool __ro_after_init opt_fb_clear_mmio; static bool __ro_after_init opt_fb_clear_mmio;
static int8_t __initdata opt_gds_mit = -1;
static int __init cf_check parse_spec_ctrl(const char *s) static int __init cf_check parse_spec_ctrl(const char *s)
{ {
@@ -119,6 +120,7 @@ static int __init cf_check parse_spec_ctrl(const char *s)
opt_branch_harden = false; opt_branch_harden = false;
opt_srb_lock = 0; opt_srb_lock = 0;
opt_unpriv_mmio = false; opt_unpriv_mmio = false;
opt_gds_mit = 0;
} }
else if ( val > 0 ) else if ( val > 0 )
rc = -EINVAL; rc = -EINVAL;
@@ -269,6 +271,8 @@ static int __init cf_check parse_spec_ctrl(const char *s)
opt_srb_lock = val; opt_srb_lock = val;
else if ( (val = parse_boolean("unpriv-mmio", s, ss)) >= 0 ) else if ( (val = parse_boolean("unpriv-mmio", s, ss)) >= 0 )
opt_unpriv_mmio = val; opt_unpriv_mmio = val;
else if ( (val = parse_boolean("gds-mit", s, ss)) >= 0 )
opt_gds_mit = val;
else else
rc = -EINVAL; rc = -EINVAL;
@@ -1267,6 +1271,158 @@ static __init void mds_calculations(void)
} }
} }
static bool __init cpu_has_gds(void)
{
/*
* Any part advertising GDS_NO should be not vulnerable to GDS. This
* includes cases where the hypervisor is mitigating behind our backs, or
* has synthesized GDS_NO on older parts for levelling purposes.
*/
if ( cpu_has_gds_no )
return false;
/*
* On real hardware the GDS_CTRL control only exists on parts vulnerable
* to GDS and with up-to-date microcode. It might also be virtualised by
* an aware hypervisor, meaning "somewhere you might migrate to is
* vulnerable".
*/
if ( cpu_has_gds_ctrl )
return true;
/*
* An attacker requires the use of the AVX2 GATHER instructions to leak
* data with GDS. However, the only way to block those instructions is to
* prevent XCR0[2] from being set, which is original AVX. A hypervisor
* might do this as a stopgap mitigation.
*/
if ( !cpu_has_avx )
return false;
/*
* GDS affects the Core line from Skylake up to but not including Golden
* Cove (Alder Lake, Sapphire Rapids). Broadwell and older, and the Atom
* line, and all hybrid parts are unaffected.
*/
switch ( boot_cpu_data.x86_model )
{
case 0x55: /* Skylake/Cascade Lake/Cooper Lake SP */
case 0x6a: /* Ice Lake SP */
case 0x6c: /* Ice Lake D */
case 0x7e: /* Ice Lake U/Y */
case 0x8c: /* Tiger Lake U */
case 0x8d: /* Tiger Lake H */
case 0x8e: /* Amber/Kaby/Coffee/Whiskey/Comet lake U/Y */
case 0x9e: /* Kaby/Coffee lake H/S/Xeon */
case 0xa5: /* Comet Lake H/S */
case 0xa6: /* Comet Lake U */
case 0xa7: /* Rocket Lake */
return true;
default:
/*
* If we've got here and are virtualised, we're most likely under a
* hypervisor unaware of GDS at which point we've lost. Err on the
* safe side.
*/
return cpu_has_hypervisor;
}
}
static void __init gds_calculations(void)
{
bool cpu_has_bug_gds, mitigated = false;
/* GDS is only known to affect Intel Family 6 processors at this time. */
if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
boot_cpu_data.x86 != 6 )
return;
cpu_has_bug_gds = cpu_has_gds();
/*
* If we've got GDS_CTRL, we're either native with up-to-date microcode on
* a GDS-vulnerable part, or virtualised under a GDS-aware hypervisor.
*/
if ( cpu_has_gds_ctrl )
{
bool locked;
uint64_t opt_ctrl;
if ( cpu_has_gds_no )
{
/*
* We don't expect to ever see GDS_CTL and GDS_NO set together.
* Complain loudly, and forgo playing with other features.
*/
printk(XENLOG_ERR
"FIRMWARE BUG: CPU %02x-%02x-%02x, ucode 0x%08x: GDS_CTRL && GDS_NO\n",
boot_cpu_data.x86, boot_cpu_data.x86_model,
boot_cpu_data.x86_mask, this_cpu(cpu_sig).rev);
return add_taint(TAINT_CPU_OUT_OF_SPEC);
}
rdmsrl(MSR_MCU_OPT_CTRL, opt_ctrl);
mitigated = !(opt_ctrl & MCU_OPT_CTRL_GDS_MIT_DIS);
locked = opt_ctrl & MCU_OPT_CTRL_GDS_MIT_LOCK;
/*
* Firmware will lock the GDS mitigation if e.g. SGX is active.
* Alternatively, a hypervisor might virtualise GDS_CTRL as locked.
* Warn if the mitigiation is locked and the user requested the
* opposite configuration.
*/
if ( locked )
{
if ( opt_gds_mit >= 0 && opt_gds_mit != mitigated )
printk(XENLOG_WARNING
"GDS_MIT locked by firwmare - ignoring spec-ctrl=gds-mit setting\n");
opt_gds_mit = mitigated;
}
else if ( opt_gds_mit == -1 )
opt_gds_mit = cpu_has_bug_gds; /* Mitigate GDS by default */
/*
* Latch our choice of GDS_MIT for all CPUs to pick up. If LOCK is
* set, we latch the same value as it currently holds.
*/
set_in_mcu_opt_ctrl(MCU_OPT_CTRL_GDS_MIT_DIS,
opt_gds_mit ? 0 : MCU_OPT_CTRL_GDS_MIT_DIS);
mitigated = opt_gds_mit;
}
else if ( opt_gds_mit == -1 )
opt_gds_mit = cpu_has_bug_gds; /* Mitigate GDS by default */
/*
* If we think we're not on vulnerable hardware, or we've mitigated GDS,
* synthesize GDS_NO. This is mostly for the benefit of guests, to inform
* them not to panic.
*/
if ( !cpu_has_bug_gds || mitigated )
return setup_force_cpu_cap(X86_FEATURE_GDS_NO);
/*
* If all else has failed, mitigate by disabling AVX. This prevents
* guests from enabling %xcr0.ymm, thereby blocking the use of VGATHER
* instructions.
*
* There's at least one affected CPU not expected to recieve a microcode
* update, and this is the only remaining mitigation.
*
* If we're virtualised, this prevents our guests attacking each other,
* but it doesn't stop the outer hypervisor's guests attacking us. Leave
* a note to this effect.
*/
if ( cpu_has_avx && opt_gds_mit )
{
setup_clear_cpu_cap(X86_FEATURE_AVX);
printk(XENLOG_WARNING "Mitigating GDS by disabling AVX%s\n",
cpu_has_hypervisor ?
" while virtualised - protections are best-effort" : "");
}
}
void spec_ctrl_init_domain(struct domain *d) void spec_ctrl_init_domain(struct domain *d)
{ {
bool pv = is_pv_domain(d); bool pv = is_pv_domain(d);
@@ -1746,6 +1902,8 @@ void __init init_speculation_mitigations(void)
opt_srb_lock ? 0 : MCU_OPT_CTRL_RNGDS_MITG_DIS); opt_srb_lock ? 0 : MCU_OPT_CTRL_RNGDS_MITG_DIS);
} }
gds_calculations();
print_details(thunk); print_details(thunk);
/* /*
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.