Skip to content

Commit 7e5b3c2

Browse files
Mark GrossKAGA-KOKO
authored andcommitted
x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation
SRBDS is an MDS-like speculative side channel that can leak bits from the random number generator (RNG) across cores and threads. New microcode serializes the processor access during the execution of RDRAND and RDSEED. This ensures that the shared buffer is overwritten before it is released for reuse. While it is present on all affected CPU models, the microcode mitigation is not needed on models that enumerate ARCH_CAPABILITIES[MDS_NO] in the cases where TSX is not supported or has been disabled with TSX_CTRL. The mitigation is activated by default on affected processors and it increases latency for RDRAND and RDSEED instructions. Among other effects this will reduce throughput from /dev/urandom. * Enable administrator to configure the mitigation off when desired using either mitigations=off or srbds=off. * Export vulnerability status via sysfs * Rename file-scoped macros to apply for non-whitelist table initializations. [ bp: Massage, - s/VULNBL_INTEL_STEPPING/VULNBL_INTEL_STEPPINGS/g, - do not read arch cap MSR a second time in tsx_fused_off() - just pass it in, - flip check in cpu_set_bug_bits() to save an indentation level, - reflow comments. jpoimboe: s/Mitigated/Mitigation/ in user-visible strings tglx: Dropped the fused off magic for now ] Signed-off-by: Mark Gross <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Tony Luck <[email protected]> Reviewed-by: Pawan Gupta <[email protected]> Reviewed-by: Josh Poimboeuf <[email protected]> Tested-by: Neelima Krishnan <[email protected]>
1 parent 93920f6 commit 7e5b3c2

File tree

8 files changed

+173
-0
lines changed

8 files changed

+173
-0
lines changed

Documentation/ABI/testing/sysfs-devices-system-cpu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ What: /sys/devices/system/cpu/vulnerabilities
492492
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
493493
/sys/devices/system/cpu/vulnerabilities/l1tf
494494
/sys/devices/system/cpu/vulnerabilities/mds
495+
/sys/devices/system/cpu/vulnerabilities/srbds
495496
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
496497
/sys/devices/system/cpu/vulnerabilities/itlb_multihit
497498
Date: January 2018

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4757,6 +4757,26 @@
47574757
the kernel will oops in either "warn" or "fatal"
47584758
mode.
47594759

4760+
srbds= [X86,INTEL]
4761+
Control the Special Register Buffer Data Sampling
4762+
(SRBDS) mitigation.
4763+
4764+
Certain CPUs are vulnerable to an MDS-like
4765+
exploit which can leak bits from the random
4766+
number generator.
4767+
4768+
By default, this issue is mitigated by
4769+
microcode. However, the microcode fix can cause
4770+
the RDRAND and RDSEED instructions to become
4771+
much slower. Among other effects, this will
4772+
result in reduced throughput from /dev/urandom.
4773+
4774+
The microcode mitigation can be disabled with
4775+
the following option:
4776+
4777+
off: Disable mitigation and remove
4778+
performance impact to RDRAND and RDSEED
4779+
47604780
srcutree.counter_wrap_check [KNL]
47614781
Specifies how frequently to check for
47624782
grace-period sequence counter wrap for the

arch/x86/include/asm/cpufeatures.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@
362362
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
363363
#define X86_FEATURE_FSRM (18*32+ 4) /* Fast Short Rep Mov */
364364
#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
365+
#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */
365366
#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
366367
#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
367368
#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
@@ -407,5 +408,6 @@
407408
#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
408409
#define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
409410
#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
411+
#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
410412

411413
#endif /* _ASM_X86_CPUFEATURES_H */

arch/x86/include/asm/msr-index.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@
128128
#define TSX_CTRL_RTM_DISABLE BIT(0) /* Disable RTM feature */
129129
#define TSX_CTRL_CPUID_CLEAR BIT(1) /* Disable TSX enumeration */
130130

131+
/* SRBDS support */
132+
#define MSR_IA32_MCU_OPT_CTRL 0x00000123
133+
#define RNGDS_MITG_DIS BIT(0)
134+
131135
#define MSR_IA32_SYSENTER_CS 0x00000174
132136
#define MSR_IA32_SYSENTER_ESP 0x00000175
133137
#define MSR_IA32_SYSENTER_EIP 0x00000176

arch/x86/kernel/cpu/bugs.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ static void __init l1tf_select_mitigation(void);
4141
static void __init mds_select_mitigation(void);
4242
static void __init mds_print_mitigation(void);
4343
static void __init taa_select_mitigation(void);
44+
static void __init srbds_select_mitigation(void);
4445

4546
/* The base value of the SPEC_CTRL MSR that always has to be preserved. */
4647
u64 x86_spec_ctrl_base;
@@ -108,6 +109,7 @@ void __init check_bugs(void)
108109
l1tf_select_mitigation();
109110
mds_select_mitigation();
110111
taa_select_mitigation();
112+
srbds_select_mitigation();
111113

112114
/*
113115
* As MDS and TAA mitigations are inter-related, print MDS
@@ -397,6 +399,97 @@ static int __init tsx_async_abort_parse_cmdline(char *str)
397399
}
398400
early_param("tsx_async_abort", tsx_async_abort_parse_cmdline);
399401

402+
#undef pr_fmt
403+
#define pr_fmt(fmt) "SRBDS: " fmt
404+
405+
enum srbds_mitigations {
406+
SRBDS_MITIGATION_OFF,
407+
SRBDS_MITIGATION_UCODE_NEEDED,
408+
SRBDS_MITIGATION_FULL,
409+
SRBDS_MITIGATION_TSX_OFF,
410+
SRBDS_MITIGATION_HYPERVISOR,
411+
};
412+
413+
static enum srbds_mitigations srbds_mitigation __ro_after_init = SRBDS_MITIGATION_FULL;
414+
415+
static const char * const srbds_strings[] = {
416+
[SRBDS_MITIGATION_OFF] = "Vulnerable",
417+
[SRBDS_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode",
418+
[SRBDS_MITIGATION_FULL] = "Mitigation: Microcode",
419+
[SRBDS_MITIGATION_TSX_OFF] = "Mitigation: TSX disabled",
420+
[SRBDS_MITIGATION_HYPERVISOR] = "Unknown: Dependent on hypervisor status",
421+
};
422+
423+
static bool srbds_off;
424+
425+
void update_srbds_msr(void)
426+
{
427+
u64 mcu_ctrl;
428+
429+
if (!boot_cpu_has_bug(X86_BUG_SRBDS))
430+
return;
431+
432+
if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
433+
return;
434+
435+
if (srbds_mitigation == SRBDS_MITIGATION_UCODE_NEEDED)
436+
return;
437+
438+
rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
439+
440+
switch (srbds_mitigation) {
441+
case SRBDS_MITIGATION_OFF:
442+
case SRBDS_MITIGATION_TSX_OFF:
443+
mcu_ctrl |= RNGDS_MITG_DIS;
444+
break;
445+
case SRBDS_MITIGATION_FULL:
446+
mcu_ctrl &= ~RNGDS_MITG_DIS;
447+
break;
448+
default:
449+
break;
450+
}
451+
452+
wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
453+
}
454+
455+
static void __init srbds_select_mitigation(void)
456+
{
457+
u64 ia32_cap;
458+
459+
if (!boot_cpu_has_bug(X86_BUG_SRBDS))
460+
return;
461+
462+
/*
463+
* Check to see if this is one of the MDS_NO systems supporting
464+
* TSX that are only exposed to SRBDS when TSX is enabled.
465+
*/
466+
ia32_cap = x86_read_arch_cap_msr();
467+
if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM))
468+
srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
469+
else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
470+
srbds_mitigation = SRBDS_MITIGATION_HYPERVISOR;
471+
else if (!boot_cpu_has(X86_FEATURE_SRBDS_CTRL))
472+
srbds_mitigation = SRBDS_MITIGATION_UCODE_NEEDED;
473+
else if (cpu_mitigations_off() || srbds_off)
474+
srbds_mitigation = SRBDS_MITIGATION_OFF;
475+
476+
update_srbds_msr();
477+
pr_info("%s\n", srbds_strings[srbds_mitigation]);
478+
}
479+
480+
static int __init srbds_parse_cmdline(char *str)
481+
{
482+
if (!str)
483+
return -EINVAL;
484+
485+
if (!boot_cpu_has_bug(X86_BUG_SRBDS))
486+
return 0;
487+
488+
srbds_off = !strcmp(str, "off");
489+
return 0;
490+
}
491+
early_param("srbds", srbds_parse_cmdline);
492+
400493
#undef pr_fmt
401494
#define pr_fmt(fmt) "Spectre V1 : " fmt
402495

@@ -1528,6 +1621,11 @@ static char *ibpb_state(void)
15281621
return "";
15291622
}
15301623

1624+
static ssize_t srbds_show_state(char *buf)
1625+
{
1626+
return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
1627+
}
1628+
15311629
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
15321630
char *buf, unsigned int bug)
15331631
{
@@ -1572,6 +1670,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
15721670
case X86_BUG_ITLB_MULTIHIT:
15731671
return itlb_multihit_show_state(buf);
15741672

1673+
case X86_BUG_SRBDS:
1674+
return srbds_show_state(buf);
1675+
15751676
default:
15761677
break;
15771678
}
@@ -1618,4 +1719,9 @@ ssize_t cpu_show_itlb_multihit(struct device *dev, struct device_attribute *attr
16181719
{
16191720
return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT);
16201721
}
1722+
1723+
ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf)
1724+
{
1725+
return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS);
1726+
}
16211727
#endif

arch/x86/kernel/cpu/common.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,27 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
10751075
{}
10761076
};
10771077

1078+
#define VULNBL_INTEL_STEPPINGS(model, steppings, issues) \
1079+
X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6, \
1080+
INTEL_FAM6_##model, steppings, \
1081+
X86_FEATURE_ANY, issues)
1082+
1083+
#define SRBDS BIT(0)
1084+
1085+
static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
1086+
VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS),
1087+
VULNBL_INTEL_STEPPINGS(HASWELL, X86_STEPPING_ANY, SRBDS),
1088+
VULNBL_INTEL_STEPPINGS(HASWELL_L, X86_STEPPING_ANY, SRBDS),
1089+
VULNBL_INTEL_STEPPINGS(HASWELL_G, X86_STEPPING_ANY, SRBDS),
1090+
VULNBL_INTEL_STEPPINGS(BROADWELL_G, X86_STEPPING_ANY, SRBDS),
1091+
VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS),
1092+
VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS),
1093+
VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS),
1094+
VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPINGS(0x0, 0xC), SRBDS),
1095+
VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPINGS(0x0, 0xD), SRBDS),
1096+
{}
1097+
};
1098+
10781099
static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which)
10791100
{
10801101
const struct x86_cpu_id *m = x86_match_cpu(table);
@@ -1142,6 +1163,15 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
11421163
(ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
11431164
setup_force_cpu_bug(X86_BUG_TAA);
11441165

1166+
/*
1167+
* SRBDS affects CPUs which support RDRAND or RDSEED and are listed
1168+
* in the vulnerability blacklist.
1169+
*/
1170+
if ((cpu_has(c, X86_FEATURE_RDRAND) ||
1171+
cpu_has(c, X86_FEATURE_RDSEED)) &&
1172+
cpu_matches(cpu_vuln_blacklist, SRBDS))
1173+
setup_force_cpu_bug(X86_BUG_SRBDS);
1174+
11451175
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
11461176
return;
11471177

@@ -1594,6 +1624,7 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
15941624
mtrr_ap_init();
15951625
validate_apic_and_package_id(c);
15961626
x86_spec_ctrl_setup_ap();
1627+
update_srbds_msr();
15971628
}
15981629

15991630
static __init int setup_noclflush(char *arg)

arch/x86/kernel/cpu/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ extern void detect_ht(struct cpuinfo_x86 *c);
7777
unsigned int aperfmperf_get_khz(int cpu);
7878

7979
extern void x86_spec_ctrl_setup_ap(void);
80+
extern void update_srbds_msr(void);
8081

8182
extern u64 x86_read_arch_cap_msr(void);
8283

drivers/base/cpu.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,12 @@ ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
562562
return sprintf(buf, "Not affected\n");
563563
}
564564

565+
ssize_t __weak cpu_show_srbds(struct device *dev,
566+
struct device_attribute *attr, char *buf)
567+
{
568+
return sprintf(buf, "Not affected\n");
569+
}
570+
565571
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
566572
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
567573
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
@@ -570,6 +576,7 @@ static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
570576
static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
571577
static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
572578
static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
579+
static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
573580

574581
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
575582
&dev_attr_meltdown.attr,
@@ -580,6 +587,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
580587
&dev_attr_mds.attr,
581588
&dev_attr_tsx_async_abort.attr,
582589
&dev_attr_itlb_multihit.attr,
590+
&dev_attr_srbds.attr,
583591
NULL
584592
};
585593

0 commit comments

Comments
 (0)