Skip to content

Commit c2860ec

Browse files
bp3tk0vSherryYang1
authored andcommitted
x86/bugs: Add a Transient Scheduler Attacks mitigation
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Co-developed-by: Kim Phillips <kim.phillips@amd.com> Signed-off-by: Kim Phillips <kim.phillips@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Orabug: 38172250 CVE: CVE-2024-36350, CVE-2024-36357 Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Reviewed-by: Ankur Arora <ankur.a.arora@oracle.com> Conflicts: arch/x86/include/asm/cpufeatures.h - Use X86_BUG_AMD_APIC_C1E bit arch/x86/kernel/cpu/bugs.c - Don't set X86_FEATURE_CLEAR_CPU_BUF - Context arch/x86/include/asm/processor.h arch/x86/kernel/cpu/amd.c arch/x86/kernel/cpu/scattered.c include/linux/cpu.h - Context arch/x86/kernel/cpu/common.c - Use bit 10 for TSA - Context drivers/base/cpu.c - Opencode CPU_SHOW_VULN_FALLBACK arch/x86/kvm/svm/svm.c - Add the flush to svm_prepare_guest_switch() Signed-off-by: Sherry Yang <sherry.yang@oracle.com>
1 parent c717706 commit c2860ec

File tree

10 files changed

+183
-1
lines changed

10 files changed

+183
-1
lines changed

arch/x86/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,6 +2584,15 @@ config SLS
25842584
against straight line speculation. The kernel image might be slightly
25852585
larger.
25862586

2587+
config MITIGATION_TSA
2588+
bool "Mitigate Transient Scheduler Attacks"
2589+
depends on CPU_SUP_AMD
2590+
default y
2591+
help
2592+
Enable mitigation for Transient Scheduler Attacks. TSA is a hardware
2593+
security vulnerability on AMD CPUs which can lead to forwarding of
2594+
invalid info to subsequent instructions and thus can affect their
2595+
timing and thereby cause a leakage.
25872596
endif
25882597

25892598
config ARCH_HAS_ADD_PAGES

arch/x86/include/asm/cpufeatures.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@
415415
#define X86_FEATURE_SEV_ES (19*32+ 3) /* AMD Secure Encrypted Virtualization - Encrypted State */
416416
#define X86_FEATURE_SME_COHERENT (19*32+10) /* "" AMD hardware-enforced cache coherency */
417417

418+
#define X86_FEATURE_VERW_CLEAR (20*32+ 5) /* "" The memory form of VERW mitigates TSA */
418419
#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */
419420
#define X86_FEATURE_SBPB (20*32+27) /* "" Selective Branch Prediction Barrier */
420421
#define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
@@ -430,6 +431,8 @@
430431
#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */
431432
#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */
432433
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
434+
#define X86_FEATURE_TSA_SQ_NO (21*32+ 6) /* "" AMD CPU not vulnerable to TSA-SQ */
435+
#define X86_FEATURE_TSA_L1_NO (21*32+ 7) /* "" AMD CPU not vulnerable to TSA-L1 */
433436
#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32 + 9) /* "" Use thunk for indirect branches in lower half of cacheline */
434437

435438
/*
@@ -491,5 +494,6 @@
491494
#define X86_BUG_BHI X86_BUG(1) /* CPU is affected by Branch History Injection */
492495
#define X86_BUG_ITS X86_BUG(2) /* CPU is affected by Indirect Target Selection */
493496
#define X86_BUG_ITS_NATIVE_ONLY X86_BUG(3) /* CPU is affected by ITS, VMX is not affected */
497+
#define X86_BUG_TSA X86_BUG(4) /* CPU is affected by Transient Scheduler Attacks */
494498

495499
#endif /* _ASM_X86_CPUFEATURES_H */

arch/x86/include/asm/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,11 +930,13 @@ extern u16 amd_get_nb_id(int cpu);
930930
extern u32 amd_get_nodes_per_socket(void);
931931
extern void amd_clear_divider(void);
932932
extern bool cpu_has_ibpb_brtype_microcode(void);
933+
extern bool amd_check_tsa_microcode(void);
933934
#else
934935
static inline u16 amd_get_nb_id(int cpu) { return 0; }
935936
static inline u32 amd_get_nodes_per_socket(void) { return 0; }
936937
static inline void amd_clear_divider(void) { }
937938
static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; }
939+
static inline bool amd_check_tsa_microcode(void) { return false; }
938940
#endif
939941

940942
static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)

arch/x86/kernel/cpu/amd.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,14 @@ static void early_init_amd_mc(struct cpuinfo_x86 *c)
566566
#endif
567567
}
568568

569+
static void tsa_set_cpuid_flags(struct cpuinfo_x86 *c)
570+
{
571+
if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && c->x86 != 0x19) {
572+
setup_force_cpu_cap(X86_FEATURE_TSA_SQ_NO);
573+
setup_force_cpu_cap(X86_FEATURE_TSA_L1_NO);
574+
}
575+
}
576+
569577
static void bsp_init_amd(struct cpuinfo_x86 *c)
570578
{
571579

@@ -740,6 +748,8 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
740748
setup_clear_cpu_cap(X86_FEATURE_SEV);
741749
setup_clear_cpu_cap(X86_FEATURE_SEV_ES);
742750
}
751+
752+
tsa_set_cpuid_flags(c);
743753
}
744754

745755
static void early_init_amd(struct cpuinfo_x86 *c)
@@ -1401,6 +1411,38 @@ void amd_check_microcode(void)
14011411
on_each_cpu(zenbleed_check_cpu, NULL, 1);
14021412
}
14031413

1414+
bool amd_check_tsa_microcode(void)
1415+
{
1416+
struct cpuinfo_x86 *c = &boot_cpu_data;
1417+
bool ret = false;
1418+
1419+
if (cpu_has(c, X86_FEATURE_ZEN3)) {
1420+
if (c->x86_model == 0x1) {
1421+
if (c->x86_stepping == 0x1)
1422+
ret = c->microcode >= 0x0a0011d7;
1423+
else if (c->x86_stepping == 0x2)
1424+
ret = c->microcode >= 0x0a00123b;
1425+
} else if (c->x86_model == 0x30) {
1426+
ret = c->microcode >= 0x0a30010d;
1427+
}
1428+
} else if (cpu_has(c, X86_FEATURE_ZEN4)) {
1429+
if (c->x86_model == 0x11) {
1430+
if (c->x86_stepping == 0x1)
1431+
ret = c->microcode >= 0x0a10114c;
1432+
else if (c->x86_stepping == 0x2)
1433+
ret = c->microcode >= 0x0a10124c;
1434+
} else if (c->x86_model == 0xa0) {
1435+
if (c->x86_stepping == 0x2)
1436+
ret = c->microcode >= 0x0aa00216;
1437+
}
1438+
}
1439+
1440+
if (ret)
1441+
setup_force_cpu_cap(X86_FEATURE_VERW_CLEAR);
1442+
1443+
return ret;
1444+
}
1445+
14041446
/*
14051447
* Issue a DIV 0/1 insn to clear any division data from previous DIV
14061448
* operations.

arch/x86/kernel/cpu/bugs.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ static void srbds_select_mitigation(void);
154154
static void srso_select_mitigation(void);
155155
static void gds_select_mitigation(void);
156156
static void its_select_mitigation(void);
157+
static void tsa_select_mitigation(void);
157158

158159
static enum ssb_mitigation ssb_mode = SPEC_STORE_BYPASS_NONE;
159160

@@ -335,6 +336,8 @@ void __init cpu_select_mitigations(void)
335336
srso_select_mitigation();
336337
gds_select_mitigation();
337338
its_select_mitigation();
339+
340+
tsa_select_mitigation();
338341
}
339342

340343
void x86_spec_ctrl_set(enum spec_ctrl_set_context context)
@@ -3216,6 +3219,92 @@ static void __init srso_select_mitigation(void)
32163219
x86_pred_cmd = PRED_CMD_SBPB;
32173220
}
32183221

3222+
#undef pr_fmt
3223+
#define pr_fmt(fmt) "Transient Scheduler Attacks: " fmt
3224+
3225+
enum tsa_mitigations {
3226+
TSA_MITIGATION_NONE,
3227+
TSA_MITIGATION_UCODE_NEEDED,
3228+
TSA_MITIGATION_USER_KERNEL,
3229+
TSA_MITIGATION_VM,
3230+
TSA_MITIGATION_FULL,
3231+
};
3232+
3233+
static const char * const tsa_strings[] = {
3234+
[TSA_MITIGATION_NONE] = "Vulnerable",
3235+
[TSA_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode",
3236+
[TSA_MITIGATION_USER_KERNEL] = "Mitigation: user/kernel boundary",
3237+
[TSA_MITIGATION_VM] = "Mitigation: VM only",
3238+
[TSA_MITIGATION_FULL] = "Mitigation: enabled",
3239+
};
3240+
3241+
static enum tsa_mitigations tsa_mitigation __ro_after_init =
3242+
IS_ENABLED(CONFIG_MITIGATION_TSA) ? TSA_MITIGATION_FULL : TSA_MITIGATION_NONE;
3243+
3244+
static int __init tsa_parse_cmdline(char *str)
3245+
{
3246+
if (!str)
3247+
return -EINVAL;
3248+
3249+
if (!strcmp(str, "off"))
3250+
tsa_mitigation = TSA_MITIGATION_NONE;
3251+
else if (!strcmp(str, "on"))
3252+
tsa_mitigation = TSA_MITIGATION_FULL;
3253+
else if (!strcmp(str, "user"))
3254+
tsa_mitigation = TSA_MITIGATION_USER_KERNEL;
3255+
else if (!strcmp(str, "vm"))
3256+
tsa_mitigation = TSA_MITIGATION_VM;
3257+
else
3258+
pr_err("Ignoring unknown tsa=%s option.\n", str);
3259+
3260+
return 0;
3261+
}
3262+
early_param("tsa", tsa_parse_cmdline);
3263+
3264+
static void __init tsa_select_mitigation(void)
3265+
{
3266+
bool has_microcode = false;
3267+
3268+
if (tsa_mitigation == TSA_MITIGATION_NONE)
3269+
return;
3270+
3271+
if (cpu_mitigations_off() || !boot_cpu_has_bug(X86_BUG_TSA)) {
3272+
tsa_mitigation = TSA_MITIGATION_NONE;
3273+
return;
3274+
}
3275+
3276+
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
3277+
if (boot_cpu_has(X86_FEATURE_VERW_CLEAR)) {
3278+
has_microcode = true;
3279+
}
3280+
} else {
3281+
has_microcode = amd_check_tsa_microcode();
3282+
}
3283+
3284+
if (!has_microcode) {
3285+
tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED;
3286+
goto out;
3287+
}
3288+
3289+
switch (tsa_mitigation) {
3290+
case TSA_MITIGATION_USER_KERNEL:
3291+
static_branch_enable(&cpu_buf_idle_clear);
3292+
break;
3293+
case TSA_MITIGATION_VM:
3294+
static_branch_enable(&cpu_buf_vm_clear);
3295+
break;
3296+
case TSA_MITIGATION_FULL:
3297+
static_branch_enable(&cpu_buf_idle_clear);
3298+
static_branch_enable(&cpu_buf_vm_clear);
3299+
break;
3300+
default:
3301+
break;
3302+
}
3303+
3304+
out:
3305+
pr_info("%s\n", tsa_strings[tsa_mitigation]);
3306+
}
3307+
32193308
#undef pr_fmt
32203309
#define pr_fmt(fmt) fmt
32213310

@@ -3447,6 +3536,11 @@ static ssize_t gds_show_state(char *buf)
34473536
return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]);
34483537
}
34493538

3539+
static ssize_t tsa_show_state(char *buf)
3540+
{
3541+
return sysfs_emit(buf, "%s\n", tsa_strings[tsa_mitigation]);
3542+
}
3543+
34503544
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
34513545
char *buf, unsigned int bug)
34523546
{
@@ -3505,6 +3599,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
35053599
case X86_BUG_ITS:
35063600
return its_show_state(buf);
35073601

3602+
case X86_BUG_TSA:
3603+
return tsa_show_state(buf);
3604+
35083605
default:
35093606
break;
35103607
}
@@ -3584,4 +3681,9 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
35843681
{
35853682
return cpu_show_common(dev, attr, buf, X86_BUG_ITS);
35863683
}
3684+
3685+
ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf)
3686+
{
3687+
return cpu_show_common(dev, attr, buf, X86_BUG_TSA);
3688+
}
35873689
#endif

arch/x86/kernel/cpu/common.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,8 @@ static const struct x86_cpu_id cpu_vuln_whitelist[] = {
12731273
#define ITS BIT(8)
12741274
/* CPU is affected by Indirect Target Selection, but guest-host isolation is not affected */
12751275
#define ITS_NATIVE_ONLY BIT(9)
1276+
/* CPU is affected by Transient Scheduler Attacks */
1277+
#define TSA BIT(10)
12761278

12771279
static const struct x86_cpu_id cpu_vuln_blacklist[] = {
12781280
VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS),
@@ -1311,7 +1313,7 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] = {
13111313
VULNBL_AMD(0x16, RETBLEED),
13121314
VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO),
13131315
VULNBL_HYGON(0x18, RETBLEED | SMT_RSB),
1314-
VULNBL_AMD(0x19, SRSO),
1316+
VULNBL_AMD(0x19, SRSO | TSA),
13151317
{}
13161318
};
13171319

@@ -1523,6 +1525,12 @@ void cpu_set_bug_bits(struct cpuinfo_x86 *c)
15231525
setup_force_cpu_bug(X86_BUG_ITS_NATIVE_ONLY);
15241526
}
15251527

1528+
if (!cpu_has(c, X86_FEATURE_TSA_SQ_NO) ||
1529+
!cpu_has(c, X86_FEATURE_TSA_L1_NO)) {
1530+
if (cpu_matches(cpu_vuln_blacklist, TSA))
1531+
setup_force_cpu_bug(X86_BUG_TSA);
1532+
}
1533+
15261534
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
15271535
return;
15281536

arch/x86/kernel/cpu/scattered.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ static const struct cpuid_bit cpuid_bits[] = {
4242
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
4343
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
4444
{ X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
45+
{ X86_FEATURE_TSA_SQ_NO, CPUID_ECX, 1, 0x80000021, 0 },
46+
{ X86_FEATURE_TSA_L1_NO, CPUID_ECX, 2, 0x80000021, 0 },
47+
4548
{ 0, 0, 0, 0, 0 }
4649
};
4750

arch/x86/kvm/svm/svm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3368,6 +3368,8 @@ static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
33683368

33693369
static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu)
33703370
{
3371+
if (static_branch_likely(&cpu_buf_vm_clear))
3372+
x86_clear_cpu_buffers();
33713373
}
33723374

33733375
static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)

drivers/base/cpu.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,12 @@ ssize_t __weak cpu_show_indirect_target_selection(struct device *dev,
606606
return sysfs_emit(buf, "Not affected\n");
607607
}
608608

609+
ssize_t __weak cpu_show_tsa(struct device *dev,
610+
struct device_attribute *attr, char *buf)
611+
{
612+
return sysfs_emit(buf, "Not affected\n");
613+
}
614+
609615
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
610616
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
611617
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
@@ -620,6 +626,7 @@ static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
620626
static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
621627
static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
622628
static DEVICE_ATTR(indirect_target_selection, 0444, cpu_show_indirect_target_selection, NULL);
629+
static DEVICE_ATTR(tsa, 0444, cpu_show_tsa, NULL);
623630

624631
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
625632
&dev_attr_meltdown.attr,
@@ -636,6 +643,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
636643
&dev_attr_spec_rstack_overflow.attr,
637644
&dev_attr_gather_data_sampling.attr,
638645
&dev_attr_indirect_target_selection.attr,
646+
&dev_attr_tsa.attr,
639647
NULL
640648
};
641649

include/linux/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ extern ssize_t cpu_show_spec_rstack_overflow(struct device *dev,
7474
struct device_attribute *attr, char *buf);
7575
extern ssize_t cpu_show_indirect_target_selection(struct device *dev,
7676
struct device_attribute *attr, char *buf);
77+
extern ssize_t cpu_show_tsa(struct device *dev,
78+
struct device_attribute *attr, char *buf);
7779

7880
extern __printf(4, 5)
7981
struct device *cpu_device_create(struct device *parent, void *drvdata,

0 commit comments

Comments
 (0)