Skip to content

Commit 627277b

Browse files
committed
Merge tag 'arm64_cbpf_mitigation_2025_05_08' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 cBPF BHB mitigation from James Morse: "This adds the BHB mitigation into the code JITted for cBPF programs as these can be loaded by unprivileged users via features like seccomp. The existing mechanisms to disable the BHB mitigation will also prevent the mitigation being JITted. In addition, cBPF programs loaded by processes with the SYS_ADMIN capability are not mitigated as these could equally load an eBPF program that does the same thing. For good measure, the list of 'k' values for CPU's local mitigations is updated from the version on arm's website" * tag 'arm64_cbpf_mitigation_2025_05_08' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: proton-pack: Add new CPUs 'k' values for branch mitigation arm64: bpf: Only mitigate cBPF programs loaded by unprivileged users arm64: bpf: Add BHB mitigation to the epilogue for cBPF programs arm64: proton-pack: Expose whether the branchy loop k value arm64: proton-pack: Expose whether the platform is mitigated by firmware arm64: insn: Add support for encoding DSB
2 parents 6f5bf94 + efe676a commit 627277b

File tree

6 files changed

+108
-28
lines changed

6 files changed

+108
-28
lines changed

arch/arm64/include/asm/cputype.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
8282
#define ARM_CPU_PART_CORTEX_X1 0xD44
8383
#define ARM_CPU_PART_CORTEX_A510 0xD46
84+
#define ARM_CPU_PART_CORTEX_X1C 0xD4C
8485
#define ARM_CPU_PART_CORTEX_A520 0xD80
8586
#define ARM_CPU_PART_CORTEX_A710 0xD47
8687
#define ARM_CPU_PART_CORTEX_A715 0xD4D
@@ -168,6 +169,7 @@
168169
#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
169170
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
170171
#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
172+
#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C)
171173
#define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520)
172174
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
173175
#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)

arch/arm64/include/asm/insn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ u32 aarch64_insn_gen_cas(enum aarch64_insn_register result,
706706
}
707707
#endif
708708
u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type);
709+
u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type);
709710
u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result,
710711
enum aarch64_insn_system_register sysreg);
711712

arch/arm64/include/asm/spectre.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ enum mitigation_state arm64_get_meltdown_state(void);
9797

9898
enum mitigation_state arm64_get_spectre_bhb_state(void);
9999
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
100+
extern bool __nospectre_bhb;
101+
u8 get_spectre_bhb_loop_value(void);
102+
bool is_spectre_bhb_fw_mitigated(void);
100103
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
101104
bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr);
102105

arch/arm64/kernel/proton-pack.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ static u8 spectre_bhb_loop_affected(void)
891891
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
892892
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
893893
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
894+
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C),
894895
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
895896
MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
896897
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
@@ -999,6 +1000,11 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
9991000
return true;
10001001
}
10011002

1003+
u8 get_spectre_bhb_loop_value(void)
1004+
{
1005+
return max_bhb_k;
1006+
}
1007+
10021008
static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
10031009
{
10041010
const char *v = arm64_get_bp_hardening_vector(slot);
@@ -1016,7 +1022,7 @@ static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
10161022
isb();
10171023
}
10181024

1019-
static bool __read_mostly __nospectre_bhb;
1025+
bool __read_mostly __nospectre_bhb;
10201026
static int __init parse_spectre_bhb_param(char *str)
10211027
{
10221028
__nospectre_bhb = true;
@@ -1094,6 +1100,11 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
10941100
update_mitigation_state(&spectre_bhb_state, state);
10951101
}
10961102

1103+
bool is_spectre_bhb_fw_mitigated(void)
1104+
{
1105+
return test_bit(BHB_FW, &system_bhb_mitigations);
1106+
}
1107+
10971108
/* Patched to NOP when enabled */
10981109
void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt,
10991110
__le32 *origptr,

arch/arm64/lib/insn.c

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*
66
* Copyright (C) 2014-2016 Zi Shen Lim <[email protected]>
77
*/
8+
#include <linux/bitfield.h>
89
#include <linux/bitops.h>
910
#include <linux/bug.h>
1011
#include <linux/printk.h>
@@ -1500,43 +1501,41 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
15001501
return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
15011502
}
15021503

1503-
u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
1504+
static u32 __get_barrier_crm_val(enum aarch64_insn_mb_type type)
15041505
{
1505-
u32 opt;
1506-
u32 insn;
1507-
15081506
switch (type) {
15091507
case AARCH64_INSN_MB_SY:
1510-
opt = 0xf;
1511-
break;
1508+
return 0xf;
15121509
case AARCH64_INSN_MB_ST:
1513-
opt = 0xe;
1514-
break;
1510+
return 0xe;
15151511
case AARCH64_INSN_MB_LD:
1516-
opt = 0xd;
1517-
break;
1512+
return 0xd;
15181513
case AARCH64_INSN_MB_ISH:
1519-
opt = 0xb;
1520-
break;
1514+
return 0xb;
15211515
case AARCH64_INSN_MB_ISHST:
1522-
opt = 0xa;
1523-
break;
1516+
return 0xa;
15241517
case AARCH64_INSN_MB_ISHLD:
1525-
opt = 0x9;
1526-
break;
1518+
return 0x9;
15271519
case AARCH64_INSN_MB_NSH:
1528-
opt = 0x7;
1529-
break;
1520+
return 0x7;
15301521
case AARCH64_INSN_MB_NSHST:
1531-
opt = 0x6;
1532-
break;
1522+
return 0x6;
15331523
case AARCH64_INSN_MB_NSHLD:
1534-
opt = 0x5;
1535-
break;
1524+
return 0x5;
15361525
default:
1537-
pr_err("%s: unknown dmb type %d\n", __func__, type);
1526+
pr_err("%s: unknown barrier type %d\n", __func__, type);
15381527
return AARCH64_BREAK_FAULT;
15391528
}
1529+
}
1530+
1531+
u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
1532+
{
1533+
u32 opt;
1534+
u32 insn;
1535+
1536+
opt = __get_barrier_crm_val(type);
1537+
if (opt == AARCH64_BREAK_FAULT)
1538+
return AARCH64_BREAK_FAULT;
15401539

15411540
insn = aarch64_insn_get_dmb_value();
15421541
insn &= ~GENMASK(11, 8);
@@ -1545,6 +1544,21 @@ u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
15451544
return insn;
15461545
}
15471546

1547+
u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type)
1548+
{
1549+
u32 opt, insn;
1550+
1551+
opt = __get_barrier_crm_val(type);
1552+
if (opt == AARCH64_BREAK_FAULT)
1553+
return AARCH64_BREAK_FAULT;
1554+
1555+
insn = aarch64_insn_get_dsb_base_value();
1556+
insn &= ~GENMASK(11, 8);
1557+
insn |= (opt << 8);
1558+
1559+
return insn;
1560+
}
1561+
15481562
u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result,
15491563
enum aarch64_insn_system_register sysreg)
15501564
{

arch/arm64/net/bpf_jit_comp.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#define pr_fmt(fmt) "bpf_jit: " fmt
99

10+
#include <linux/arm-smccc.h>
1011
#include <linux/bitfield.h>
1112
#include <linux/bpf.h>
1213
#include <linux/filter.h>
@@ -17,6 +18,7 @@
1718
#include <asm/asm-extable.h>
1819
#include <asm/byteorder.h>
1920
#include <asm/cacheflush.h>
21+
#include <asm/cpufeature.h>
2022
#include <asm/debug-monitors.h>
2123
#include <asm/insn.h>
2224
#include <asm/text-patching.h>
@@ -939,7 +941,51 @@ static void build_plt(struct jit_ctx *ctx)
939941
plt->target = (u64)&dummy_tramp;
940942
}
941943

942-
static void build_epilogue(struct jit_ctx *ctx)
944+
/* Clobbers BPF registers 1-4, aka x0-x3 */
945+
static void __maybe_unused build_bhb_mitigation(struct jit_ctx *ctx)
946+
{
947+
const u8 r1 = bpf2a64[BPF_REG_1]; /* aka x0 */
948+
u8 k = get_spectre_bhb_loop_value();
949+
950+
if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY) ||
951+
cpu_mitigations_off() || __nospectre_bhb ||
952+
arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE)
953+
return;
954+
955+
if (capable(CAP_SYS_ADMIN))
956+
return;
957+
958+
if (supports_clearbhb(SCOPE_SYSTEM)) {
959+
emit(aarch64_insn_gen_hint(AARCH64_INSN_HINT_CLEARBHB), ctx);
960+
return;
961+
}
962+
963+
if (k) {
964+
emit_a64_mov_i64(r1, k, ctx);
965+
emit(A64_B(1), ctx);
966+
emit(A64_SUBS_I(true, r1, r1, 1), ctx);
967+
emit(A64_B_(A64_COND_NE, -2), ctx);
968+
emit(aarch64_insn_gen_dsb(AARCH64_INSN_MB_ISH), ctx);
969+
emit(aarch64_insn_get_isb_value(), ctx);
970+
}
971+
972+
if (is_spectre_bhb_fw_mitigated()) {
973+
emit(A64_ORR_I(false, r1, AARCH64_INSN_REG_ZR,
974+
ARM_SMCCC_ARCH_WORKAROUND_3), ctx);
975+
switch (arm_smccc_1_1_get_conduit()) {
976+
case SMCCC_CONDUIT_HVC:
977+
emit(aarch64_insn_get_hvc_value(), ctx);
978+
break;
979+
case SMCCC_CONDUIT_SMC:
980+
emit(aarch64_insn_get_smc_value(), ctx);
981+
break;
982+
default:
983+
pr_err_once("Firmware mitigation enabled with unknown conduit\n");
984+
}
985+
}
986+
}
987+
988+
static void build_epilogue(struct jit_ctx *ctx, bool was_classic)
943989
{
944990
const u8 r0 = bpf2a64[BPF_REG_0];
945991
const u8 ptr = bpf2a64[TCCNT_PTR];
@@ -952,10 +998,13 @@ static void build_epilogue(struct jit_ctx *ctx)
952998

953999
emit(A64_POP(A64_ZR, ptr, A64_SP), ctx);
9541000

1001+
if (was_classic)
1002+
build_bhb_mitigation(ctx);
1003+
9551004
/* Restore FP/LR registers */
9561005
emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
9571006

958-
/* Set return value */
1007+
/* Move the return value from bpf:r0 (aka x7) to x0 */
9591008
emit(A64_MOV(1, A64_R(0), r0), ctx);
9601009

9611010
/* Authenticate lr */
@@ -1898,7 +1947,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
18981947
}
18991948

19001949
ctx.epilogue_offset = ctx.idx;
1901-
build_epilogue(&ctx);
1950+
build_epilogue(&ctx, was_classic);
19021951
build_plt(&ctx);
19031952

19041953
extable_align = __alignof__(struct exception_table_entry);
@@ -1961,7 +2010,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
19612010
goto out_free_hdr;
19622011
}
19632012

1964-
build_epilogue(&ctx);
2013+
build_epilogue(&ctx, was_classic);
19652014
build_plt(&ctx);
19662015

19672016
/* Extra pass to validate JITed code. */

0 commit comments

Comments
 (0)