Skip to content

Commit 7005cad

Browse files
borkmanndavem330
authored andcommitted
bpf, arm64: use separate register for state in stxr
Will reported that in BPF_XADD we must use a different register in stxr instruction for the status flag due to otherwise CONSTRAINED UNPREDICTABLE behavior per architecture. Reference manual says [1]: If s == t, then one of the following behaviors must occur: * The instruction is UNDEFINED. * The instruction executes as a NOP. * The instruction performs the store to the specified address, but the value stored is UNKNOWN. Thus, use a different temporary register for the status flag to fix it. Disassembly extract from test 226/STX_XADD_DW from test_bpf.ko: [...] 0000003c: c85f7d4b ldxr x11, [x10] 00000040: 8b07016b add x11, x11, x7 00000044: c80c7d4b stxr w12, x11, [x10] 00000048: 35ffffac cbnz w12, 0x0000003c [...] [1] https://static.docs.arm.com/ddi0487/b/DDI0487B_a_armv8_arm.pdf, p.6132 Fixes: 85f68fe ("bpf, arm64: implement jiting of BPF_XADD") Reported-by: Will Deacon <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Will Deacon <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e173db3 commit 7005cad

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

arch/arm64/net/bpf_jit_comp.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int bpf_jit_enable __read_mostly;
3636
#define TMP_REG_1 (MAX_BPF_JIT_REG + 0)
3737
#define TMP_REG_2 (MAX_BPF_JIT_REG + 1)
3838
#define TCALL_CNT (MAX_BPF_JIT_REG + 2)
39+
#define TMP_REG_3 (MAX_BPF_JIT_REG + 3)
3940

4041
/* Map BPF registers to A64 registers */
4142
static const int bpf2a64[] = {
@@ -57,6 +58,7 @@ static const int bpf2a64[] = {
5758
/* temporary registers for internal BPF JIT */
5859
[TMP_REG_1] = A64_R(10),
5960
[TMP_REG_2] = A64_R(11),
61+
[TMP_REG_3] = A64_R(12),
6062
/* tail_call_cnt */
6163
[TCALL_CNT] = A64_R(26),
6264
/* temporary register for blinding constants */
@@ -319,6 +321,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
319321
const u8 src = bpf2a64[insn->src_reg];
320322
const u8 tmp = bpf2a64[TMP_REG_1];
321323
const u8 tmp2 = bpf2a64[TMP_REG_2];
324+
const u8 tmp3 = bpf2a64[TMP_REG_3];
322325
const s16 off = insn->off;
323326
const s32 imm = insn->imm;
324327
const int i = insn - ctx->prog->insnsi;
@@ -689,10 +692,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
689692
emit(A64_PRFM(tmp, PST, L1, STRM), ctx);
690693
emit(A64_LDXR(isdw, tmp2, tmp), ctx);
691694
emit(A64_ADD(isdw, tmp2, tmp2, src), ctx);
692-
emit(A64_STXR(isdw, tmp2, tmp, tmp2), ctx);
695+
emit(A64_STXR(isdw, tmp2, tmp, tmp3), ctx);
693696
jmp_offset = -3;
694697
check_imm19(jmp_offset);
695-
emit(A64_CBNZ(0, tmp2, jmp_offset), ctx);
698+
emit(A64_CBNZ(0, tmp3, jmp_offset), ctx);
696699
break;
697700

698701
/* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */

0 commit comments

Comments
 (0)