Skip to content

Commit f5e81d1

Browse files
committed
bpf: Introduce BPF nospec instruction for mitigating Spectre v4
In case of JITs, each of the JIT backends compiles the BPF nospec instruction /either/ to a machine instruction which emits a speculation barrier /or/ to /no/ machine instruction in case the underlying architecture is not affected by Speculative Store Bypass or has different mitigations in place already. This covers both x86 and (implicitly) arm64: In case of x86, we use 'lfence' instruction for mitigation. In case of arm64, we rely on the firmware mitigation as controlled via the ssbd kernel parameter. Whenever the mitigation is enabled, it works for all of the kernel code with no need to provide any additional instructions here (hence only comment in arm64 JIT). Other archs can follow as needed. The BPF nospec instruction is specifically targeting Spectre v4 since i) we don't use a serialization barrier for the Spectre v1 case, and ii) mitigation instructions for v1 and v4 might be different on some archs. The BPF nospec is required for a future commit, where the BPF verifier does annotate intermediate BPF programs with speculation barriers. Co-developed-by: Piotr Krysiuk <[email protected]> Co-developed-by: Benedict Schlueter <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: Piotr Krysiuk <[email protected]> Signed-off-by: Benedict Schlueter <[email protected]> Acked-by: Alexei Starovoitov <[email protected]>
1 parent f1fdee3 commit f5e81d1

File tree

14 files changed

+102
-8
lines changed

14 files changed

+102
-8
lines changed

arch/arm/net/bpf_jit_32.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
16021602
rn = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
16031603
emit_ldx_r(dst, rn, off, ctx, BPF_SIZE(code));
16041604
break;
1605+
/* speculation barrier */
1606+
case BPF_ST | BPF_NOSPEC:
1607+
break;
16051608
/* ST: *(size *)(dst + off) = imm */
16061609
case BPF_ST | BPF_MEM | BPF_W:
16071610
case BPF_ST | BPF_MEM | BPF_H:

arch/arm64/net/bpf_jit_comp.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,19 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
823823
return ret;
824824
break;
825825

826+
/* speculation barrier */
827+
case BPF_ST | BPF_NOSPEC:
828+
/*
829+
* Nothing required here.
830+
*
831+
* In case of arm64, we rely on the firmware mitigation of
832+
* Speculative Store Bypass as controlled via the ssbd kernel
833+
* parameter. Whenever the mitigation is enabled, it works
834+
* for all of the kernel code with no need to provide any
835+
* additional instructions.
836+
*/
837+
break;
838+
826839
/* ST: *(size *)(dst + off) = imm */
827840
case BPF_ST | BPF_MEM | BPF_W:
828841
case BPF_ST | BPF_MEM | BPF_H:

arch/mips/net/ebpf_jit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,9 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
13551355
}
13561356
break;
13571357

1358+
case BPF_ST | BPF_NOSPEC: /* speculation barrier */
1359+
break;
1360+
13581361
case BPF_ST | BPF_B | BPF_MEM:
13591362
case BPF_ST | BPF_H | BPF_MEM:
13601363
case BPF_ST | BPF_W | BPF_MEM:

arch/powerpc/net/bpf_jit_comp32.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,12 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
737737
}
738738
break;
739739

740+
/*
741+
* BPF_ST NOSPEC (speculation barrier)
742+
*/
743+
case BPF_ST | BPF_NOSPEC:
744+
break;
745+
740746
/*
741747
* BPF_ST(X)
742748
*/

arch/powerpc/net/bpf_jit_comp64.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,12 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
627627
}
628628
break;
629629

630+
/*
631+
* BPF_ST NOSPEC (speculation barrier)
632+
*/
633+
case BPF_ST | BPF_NOSPEC:
634+
break;
635+
630636
/*
631637
* BPF_ST(X)
632638
*/

arch/riscv/net/bpf_jit_comp32.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
12511251
return -1;
12521252
break;
12531253

1254+
/* speculation barrier */
1255+
case BPF_ST | BPF_NOSPEC:
1256+
break;
1257+
12541258
case BPF_ST | BPF_MEM | BPF_B:
12551259
case BPF_ST | BPF_MEM | BPF_H:
12561260
case BPF_ST | BPF_MEM | BPF_W:

arch/riscv/net/bpf_jit_comp64.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,10 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
939939
emit_ld(rd, 0, RV_REG_T1, ctx);
940940
break;
941941

942+
/* speculation barrier */
943+
case BPF_ST | BPF_NOSPEC:
944+
break;
945+
942946
/* ST: *(size *)(dst + off) = imm */
943947
case BPF_ST | BPF_MEM | BPF_B:
944948
emit_imm(RV_REG_T1, imm, ctx);

arch/s390/net/bpf_jit_comp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,11 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
11531153
break;
11541154
}
11551155
break;
1156+
/*
1157+
* BPF_NOSPEC (speculation barrier)
1158+
*/
1159+
case BPF_ST | BPF_NOSPEC:
1160+
break;
11561161
/*
11571162
* BPF_ST(X)
11581163
*/

arch/sparc/net/bpf_jit_comp_64.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
12871287
return 1;
12881288
break;
12891289
}
1290+
/* speculation barrier */
1291+
case BPF_ST | BPF_NOSPEC:
1292+
break;
12901293
/* ST: *(size *)(dst + off) = imm */
12911294
case BPF_ST | BPF_MEM | BPF_W:
12921295
case BPF_ST | BPF_MEM | BPF_H:

arch/x86/net/bpf_jit_comp.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
12191219
}
12201220
break;
12211221

1222+
/* speculation barrier */
1223+
case BPF_ST | BPF_NOSPEC:
1224+
if (boot_cpu_has(X86_FEATURE_XMM2))
1225+
/* Emit 'lfence' */
1226+
EMIT3(0x0F, 0xAE, 0xE8);
1227+
break;
1228+
12221229
/* ST: *(u8*)(dst_reg + off) = imm */
12231230
case BPF_ST | BPF_MEM | BPF_B:
12241231
if (is_ereg(dst_reg))

0 commit comments

Comments
 (0)