From d62885ee5fbf6960bbe67d648bf43fdb10735f40 Mon Sep 17 00:00:00 2001 From: Shance Luo Date: Fri, 5 Sep 2025 13:58:21 +0800 Subject: [PATCH] anolis:x86/srso:Support to flush all types of branches in branch target buffer with the IBPB command on Hygon ANBZ: #24526 This patch is intended to fix the incorrect state of SRSO (Speculative Return Stack Overflow) on Hygon. SRSO vulnerability can be mitigated by IBPB, which is supported by Hygon, but the status display is not correct. This incorrect state is caused by the has_microcode() function. Actually, Hygon's IBPB should not be judged by this function. Hygon C86-3G IBPB can mitigate SRSO in all scenarios, and C86-4G can also mitigate SRSO in all scenarios by setting the IBPB to flush all branches. This patch adds extra judgment specific to Hygon and support to flush all types of branches in branch target buffer with IBPB command (set as ibpb-all default) to make SRSO state of all Hygon products correct and user have control over the IBPB function on Hygon C86-4G. Signed-off-by: Shance Luo --- Documentation/admin-guide/hw-vuln/srso.rst | 18 +++++ arch/x86/kernel/cpu/bugs.c | 80 ++++++++++++++++++++-- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/Documentation/admin-guide/hw-vuln/srso.rst b/Documentation/admin-guide/hw-vuln/srso.rst index e715bfc09879..54bbe96eb821 100644 --- a/Documentation/admin-guide/hw-vuln/srso.rst +++ b/Documentation/admin-guide/hw-vuln/srso.rst @@ -30,12 +30,20 @@ Affected processors AMD Zen, generations 1-4. That is, all families 0x17 and 0x19. Older processors have not been investigated. +HYGON generations 1~4. + System information and options ------------------------------ First of all, it is required that the latest microcode be loaded for mitigations to be effective. +For HYGON 1~3 CPUs, all types of branches are flushed with IBPB by default, +so no microcode or kernel parameter is needed. +For HYGON 4 CPU, all branches can be flushed by setting ibpb_brtype=ibpb-all +or by using the default value instead of loading microcode. +See the following description of the kernel parameter ibpb_brtype. + The sysfs file showing SRSO mitigation status is: /sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow @@ -105,6 +113,16 @@ The possible values in this file are: (spec_rstack_overflow=ibpb-vmexit) +In order to mitigate the attacks to the user space tasks, +IBPB must be set to flush all types of branches by setting kernel parameter ibpb_brtype. +The description of kernel parameter ibpb_brtype is as follows: +ibpb_brtype= [X86, HYGON only] + IBPB action control flag + Format: { ibpb-all | ibpb-ind } + ibpb-all -- IBPB flushes all types of branches, + this is the default value if the command line + does not specify the ibpb_brtype value. + ibpb-ind -- IBPB flushes only indirect branches. In order to exploit vulnerability, an attacker needs to: diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 332c6f24280d..cb7b1cc6819d 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -2623,6 +2623,47 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) } } +/** + * enum ibpb_brtype_cmd - IBPB action control flag + * @IBPB_FLUSH_IND: IBPB command only flushes indirect branches in branch target buffer + * @IBPB_FLUSH_ALL: IBPB command flushes all types of branches in branch target buffer + */ +enum ibpb_brtype_cmd { + IBPB_FLUSH_IND, + IBPB_FLUSH_ALL, +}; +static enum ibpb_brtype_cmd ibpb_brtype __ro_after_init = IBPB_FLUSH_ALL; +/** + * The kernel parameter ibpb_brtype is used to control + * whether IBPB flushes all branches or indirect branches: + * ibpb_brtype= [X86, HYGON only] + * IBPB action control flag + * Format: { ibpb-all | ibpb-ind } + * ibpb-all -- IBPB flushes all types of branches,this is the default value. + * ibpb-ind -- IBPB flushes only indirect branches. + */ +static int __init ibpb_brtype_cmdline(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "ibpb-all")) { + ibpb_brtype = IBPB_FLUSH_ALL; + pr_info("IBPB flushes all branches.\n"); + } else if (!strcmp(str, "ibpb-ind")) { + ibpb_brtype = IBPB_FLUSH_IND; + pr_info("IBPB flushes only indirect branches.\n"); + } else + pr_err("Ignoring unknown ibpb branch type option (%s).\n", str); + + return 0; +} +early_param("ibpb_brtype", ibpb_brtype_cmdline); + +#define HYGON_FAMILY_24 0x18 +#define HYGON_MODEL_3 3 +#define IBPB_FLUSH_ALL_BIT 55 + void x86_spec_ctrl_setup_ap(void) { if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL)) @@ -2630,6 +2671,13 @@ void x86_spec_ctrl_setup_ap(void) if (ssb_mode == SPEC_STORE_BYPASS_DISABLE) x86_amd_ssb_disable(); + + if ((boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) && + (boot_cpu_data.x86 == HYGON_FAMILY_24)) { + if ((boot_cpu_data.x86_model > HYGON_MODEL_3) && + (ibpb_brtype == IBPB_FLUSH_ALL)) + msr_set_bit(MSR_ZEN4_BP_CFG, IBPB_FLUSH_ALL_BIT); + } } bool itlb_multihit_kvm_mitigation; @@ -2815,14 +2863,34 @@ early_param("spec_rstack_overflow", srso_parse_cmdline); #define SRSO_NOTICE "WARNING: See https://kernel.org/doc/html/latest/admin-guide/hw-vuln/srso.html for mitigation options." +/* + * Whether the HYGON IBPB action flushes all types of branches is not controlled by microcode; + * Instead, it is controlled by bit 55 of MSR 0xc001102e according to kernel command line. + */ +bool ibpb_can_flush_allbranch(void) +{ + if ((boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) && + (boot_cpu_data.x86 == HYGON_FAMILY_24)) { + if (boot_cpu_data.x86_model <= HYGON_MODEL_3) { + return true; + } else if (ibpb_brtype == IBPB_FLUSH_ALL) { + msr_set_bit(MSR_ZEN4_BP_CFG, IBPB_FLUSH_ALL_BIT); + return true; + } + return false; + } + + return boot_cpu_has(X86_FEATURE_IBPB_BRTYPE); +} + static void __init srso_select_mitigation(void) { - bool has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE); + bool ibpb_allbr_flag = ibpb_can_flush_allbranch(); if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off()) goto pred_cmd; - if (has_microcode) { + if (ibpb_allbr_flag) { /* * Zen1/2 with SMT off aren't vulnerable after the right * IBPB microcode has been applied. @@ -2849,7 +2917,7 @@ static void __init srso_select_mitigation(void) goto pred_cmd; case SRSO_CMD_MICROCODE: - if (has_microcode) { + if (ibpb_allbr_flag) { srso_mitigation = SRSO_MITIGATION_MICROCODE; pr_warn(SRSO_NOTICE); } @@ -2871,7 +2939,7 @@ static void __init srso_select_mitigation(void) setup_force_cpu_cap(X86_FEATURE_SRSO); set_return_thunk(srso_return_thunk); } - if (has_microcode) + if (ibpb_allbr_flag) srso_mitigation = SRSO_MITIGATION_SAFE_RET; else srso_mitigation = SRSO_MITIGATION_SAFE_RET_UCODE_NEEDED; @@ -2883,7 +2951,7 @@ static void __init srso_select_mitigation(void) case SRSO_CMD_IBPB: if (IS_ENABLED(CONFIG_CPU_IBPB_ENTRY)) { - if (has_microcode) { + if (ibpb_allbr_flag) { setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); srso_mitigation = SRSO_MITIGATION_IBPB; @@ -2911,7 +2979,7 @@ static void __init srso_select_mitigation(void) case SRSO_CMD_IBPB_ON_VMEXIT: if (IS_ENABLED(CONFIG_CPU_IBPB_ENTRY)) { - if (has_microcode) { + if (ibpb_allbr_flag) { setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; -- Gitee