Skip to content

Commit d70f4ec

Browse files
committed
Merge branch 'bpf-jset-verifier'
Jakub Kicinski says: ==================== This is a v2 of the patch set to teach the verifier about BPF_JSET instruction. There is also a number of tests include for both basic functioning of the instruction and the verifier logic. The NFP JIT handling of JSET is tweaked. Last patch adds missing file to gitignore. Reposting part of previous series without the dead code elimination. ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2 parents 9df95e8 + 489c066 commit d70f4ec

File tree

4 files changed

+308
-50
lines changed

4 files changed

+308
-50
lines changed

drivers/net/ethernet/netronome/nfp/bpf/jit.c

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3052,26 +3052,19 @@ static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
30523052
{
30533053
const struct bpf_insn *insn = &meta->insn;
30543054
u64 imm = insn->imm; /* sign extend */
3055+
u8 dst_gpr = insn->dst_reg * 2;
30553056
swreg tmp_reg;
30563057

3057-
if (!imm) {
3058-
meta->skip = true;
3059-
return 0;
3060-
}
3061-
3062-
if (imm & ~0U) {
3063-
tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
3064-
emit_alu(nfp_prog, reg_none(),
3065-
reg_a(insn->dst_reg * 2), ALU_OP_AND, tmp_reg);
3066-
emit_br(nfp_prog, BR_BNE, insn->off, 0);
3067-
}
3068-
3069-
if (imm >> 32) {
3070-
tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
3058+
tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
3059+
emit_alu(nfp_prog, imm_b(nfp_prog),
3060+
reg_a(dst_gpr), ALU_OP_AND, tmp_reg);
3061+
/* Upper word of the mask can only be 0 or ~0 from sign extension,
3062+
* so either ignore it or OR the whole thing in.
3063+
*/
3064+
if (imm >> 32)
30713065
emit_alu(nfp_prog, reg_none(),
3072-
reg_a(insn->dst_reg * 2 + 1), ALU_OP_AND, tmp_reg);
3073-
emit_br(nfp_prog, BR_BNE, insn->off, 0);
3074-
}
3066+
reg_a(dst_gpr + 1), ALU_OP_OR, imm_b(nfp_prog));
3067+
emit_br(nfp_prog, BR_BNE, insn->off, 0);
30753068

30763069
return 0;
30773070
}

kernel/bpf/verifier.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3859,6 +3859,12 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
38593859
if (tnum_is_const(reg->var_off))
38603860
return !tnum_equals_const(reg->var_off, val);
38613861
break;
3862+
case BPF_JSET:
3863+
if ((~reg->var_off.mask & reg->var_off.value) & val)
3864+
return 1;
3865+
if (!((reg->var_off.mask | reg->var_off.value) & val))
3866+
return 0;
3867+
break;
38623868
case BPF_JGT:
38633869
if (reg->umin_value > val)
38643870
return 1;
@@ -3943,6 +3949,13 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
39433949
*/
39443950
__mark_reg_known(false_reg, val);
39453951
break;
3952+
case BPF_JSET:
3953+
false_reg->var_off = tnum_and(false_reg->var_off,
3954+
tnum_const(~val));
3955+
if (is_power_of_2(val))
3956+
true_reg->var_off = tnum_or(true_reg->var_off,
3957+
tnum_const(val));
3958+
break;
39463959
case BPF_JGT:
39473960
false_reg->umax_value = min(false_reg->umax_value, val);
39483961
true_reg->umin_value = max(true_reg->umin_value, val + 1);
@@ -4015,6 +4028,13 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
40154028
*/
40164029
__mark_reg_known(false_reg, val);
40174030
break;
4031+
case BPF_JSET:
4032+
false_reg->var_off = tnum_and(false_reg->var_off,
4033+
tnum_const(~val));
4034+
if (is_power_of_2(val))
4035+
true_reg->var_off = tnum_or(true_reg->var_off,
4036+
tnum_const(val));
4037+
break;
40184038
case BPF_JGT:
40194039
true_reg->umax_value = min(true_reg->umax_value, val - 1);
40204040
false_reg->umin_value = max(false_reg->umin_value, val);
@@ -6963,10 +6983,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
69636983
free_states(env);
69646984

69656985
if (ret == 0)
6966-
sanitize_dead_code(env);
6986+
ret = check_max_stack_depth(env);
69676987

6988+
/* instruction rewrites happen after this point */
69686989
if (ret == 0)
6969-
ret = check_max_stack_depth(env);
6990+
sanitize_dead_code(env);
69706991

69716992
if (ret == 0)
69726993
/* program is valid, convert *(u32*)(ctx + off) accesses */

tools/testing/selftests/bpf/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ test_flow_dissector
2727
flow_dissector_load
2828
test_netcnt
2929
test_section_names
30+
test_tcpnotify_user

0 commit comments

Comments
 (0)