Skip to content

Commit 0845c3d

Browse files
Yonghong SongAlexei Starovoitov
Yonghong Song
authored and
Alexei Starovoitov
committed
bpf: Support new unconditional bswap instruction
The existing 'be' and 'le' insns will do conditional bswap depends on host endianness. This patch implements unconditional bswap insns. Acked-by: Eduard Zingerman <[email protected]> Signed-off-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 1f1e864 commit 0845c3d

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

arch/x86/net/bpf_jit_comp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,7 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
13221322
break;
13231323

13241324
case BPF_ALU | BPF_END | BPF_FROM_BE:
1325+
case BPF_ALU64 | BPF_END | BPF_FROM_LE:
13251326
switch (imm32) {
13261327
case 16:
13271328
/* Emit 'ror %ax, 8' to swap lower 2 bytes */

kernel/bpf/core.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
15241524
INSN_3(ALU64, DIV, X), \
15251525
INSN_3(ALU64, MOD, X), \
15261526
INSN_2(ALU64, NEG), \
1527+
INSN_3(ALU64, END, TO_LE), \
15271528
/* Immediate based. */ \
15281529
INSN_3(ALU64, ADD, K), \
15291530
INSN_3(ALU64, SUB, K), \
@@ -1848,6 +1849,19 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
18481849
break;
18491850
}
18501851
CONT;
1852+
ALU64_END_TO_LE:
1853+
switch (IMM) {
1854+
case 16:
1855+
DST = (__force u16) __swab16(DST);
1856+
break;
1857+
case 32:
1858+
DST = (__force u32) __swab32(DST);
1859+
break;
1860+
case 64:
1861+
DST = (__force u64) __swab64(DST);
1862+
break;
1863+
}
1864+
CONT;
18511865

18521866
/* CALL */
18531867
JMP_CALL:

kernel/bpf/verifier.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,8 +3012,10 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
30123012
}
30133013
}
30143014

3015+
if (class == BPF_ALU64 && op == BPF_END && (insn->imm == 16 || insn->imm == 32))
3016+
return false;
3017+
30153018
if (class == BPF_ALU64 || class == BPF_JMP ||
3016-
/* BPF_END always use BPF_ALU class. */
30173019
(class == BPF_ALU && op == BPF_END && insn->imm == 64))
30183020
return true;
30193021

@@ -13076,7 +13078,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
1307613078
} else {
1307713079
if (insn->src_reg != BPF_REG_0 || insn->off != 0 ||
1307813080
(insn->imm != 16 && insn->imm != 32 && insn->imm != 64) ||
13079-
BPF_CLASS(insn->code) == BPF_ALU64) {
13081+
(BPF_CLASS(insn->code) == BPF_ALU64 &&
13082+
BPF_SRC(insn->code) != BPF_TO_LE)) {
1308013083
verbose(env, "BPF_END uses reserved fields\n");
1308113084
return -EINVAL;
1308213085
}

0 commit comments

Comments
 (0)