Skip to content

Commit

Permalink
Merge branch 'bpf-jset-verifier'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Daniel Borkmann committed Dec 20, 2018
2 parents 9df95e8 + 489c066 commit d70f4ec
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 50 deletions.
27 changes: 10 additions & 17 deletions drivers/net/ethernet/netronome/nfp/bpf/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -3052,26 +3052,19 @@ static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
const struct bpf_insn *insn = &meta->insn;
u64 imm = insn->imm; /* sign extend */
u8 dst_gpr = insn->dst_reg * 2;
swreg tmp_reg;

if (!imm) {
meta->skip = true;
return 0;
}

if (imm & ~0U) {
tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
emit_alu(nfp_prog, reg_none(),
reg_a(insn->dst_reg * 2), ALU_OP_AND, tmp_reg);
emit_br(nfp_prog, BR_BNE, insn->off, 0);
}

if (imm >> 32) {
tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
emit_alu(nfp_prog, imm_b(nfp_prog),
reg_a(dst_gpr), ALU_OP_AND, tmp_reg);
/* Upper word of the mask can only be 0 or ~0 from sign extension,
* so either ignore it or OR the whole thing in.
*/
if (imm >> 32)
emit_alu(nfp_prog, reg_none(),
reg_a(insn->dst_reg * 2 + 1), ALU_OP_AND, tmp_reg);
emit_br(nfp_prog, BR_BNE, insn->off, 0);
}
reg_a(dst_gpr + 1), ALU_OP_OR, imm_b(nfp_prog));
emit_br(nfp_prog, BR_BNE, insn->off, 0);

return 0;
}
Expand Down
25 changes: 23 additions & 2 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -3859,6 +3859,12 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
if (tnum_is_const(reg->var_off))
return !tnum_equals_const(reg->var_off, val);
break;
case BPF_JSET:
if ((~reg->var_off.mask & reg->var_off.value) & val)
return 1;
if (!((reg->var_off.mask | reg->var_off.value) & val))
return 0;
break;
case BPF_JGT:
if (reg->umin_value > val)
return 1;
Expand Down Expand Up @@ -3943,6 +3949,13 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
*/
__mark_reg_known(false_reg, val);
break;
case BPF_JSET:
false_reg->var_off = tnum_and(false_reg->var_off,
tnum_const(~val));
if (is_power_of_2(val))
true_reg->var_off = tnum_or(true_reg->var_off,
tnum_const(val));
break;
case BPF_JGT:
false_reg->umax_value = min(false_reg->umax_value, val);
true_reg->umin_value = max(true_reg->umin_value, val + 1);
Expand Down Expand Up @@ -4015,6 +4028,13 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
*/
__mark_reg_known(false_reg, val);
break;
case BPF_JSET:
false_reg->var_off = tnum_and(false_reg->var_off,
tnum_const(~val));
if (is_power_of_2(val))
true_reg->var_off = tnum_or(true_reg->var_off,
tnum_const(val));
break;
case BPF_JGT:
true_reg->umax_value = min(true_reg->umax_value, val - 1);
false_reg->umin_value = max(false_reg->umin_value, val);
Expand Down Expand Up @@ -6963,10 +6983,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
free_states(env);

if (ret == 0)
sanitize_dead_code(env);
ret = check_max_stack_depth(env);

/* instruction rewrites happen after this point */
if (ret == 0)
ret = check_max_stack_depth(env);
sanitize_dead_code(env);

if (ret == 0)
/* program is valid, convert *(u32*)(ctx + off) accesses */
Expand Down
1 change: 1 addition & 0 deletions tools/testing/selftests/bpf/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ test_flow_dissector
flow_dissector_load
test_netcnt
test_section_names
test_tcpnotify_user
Loading

0 comments on commit d70f4ec

Please sign in to comment.