diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2025-06-25 15:12:18 -0700 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2025-06-25 15:12:30 -0700 |
| commit | 0967f5399b64aafb0bff1e76bca45446a3e1b6af (patch) | |
| tree | 8ec7384fe76f8688d3bff5f7fbdbf9876f59d3ff /kernel/bpf/verifier.c | |
| parent | selftests/bpf: Fix usdt multispec failure with arm64/clang20 selftest build (diff) | |
| parent | selftests/bpf: Add tests for BPF_NEG range tracking logic (diff) | |
| download | linux-0967f5399b64aafb0bff1e76bca45446a3e1b6af.tar.gz linux-0967f5399b64aafb0bff1e76bca45446a3e1b6af.zip | |
Merge branch 'range-tracking-for-bpf_neg'
Song Liu says:
====================
Add range tracking for BPF_NEG. Please see commit log of 1/2 for more
details.
---
Changes v3 => v4:
1. Fix selftest verifier_value_ptr_arith.c. (Eduard)
v3: https://lore.kernel.org/bpf/20250624233328.313573-1-song@kernel.org/
Changes v2 => v3:
1. Minor changes in the selftests. (Eduard)
v2: https://lore.kernel.org/bpf/20250624220038.656646-1-song@kernel.org/
Changes v1 => v2:
1. Split new selftests to a separate patch. (Eduard)
2. Reset reg id on BPF_NEG. (Eduard)
3. Use env->fake_reg instead of a bpf_reg_state on the stack. (Eduard)
4. Add __msg for passing selftests.
v1: https://lore.kernel.org/bpf/20250624172320.2923031-1-song@kernel.org/
====================
Link: https://patch.msgid.link/20250625164025.3310203-1-song@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel/bpf/verifier.c')
| -rw-r--r-- | kernel/bpf/verifier.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index f403524bd215..2ff22ef42348 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -15182,6 +15182,7 @@ static bool is_safe_to_compute_dst_reg_range(struct bpf_insn *insn, switch (BPF_OP(insn->code)) { case BPF_ADD: case BPF_SUB: + case BPF_NEG: case BPF_AND: case BPF_XOR: case BPF_OR: @@ -15250,6 +15251,13 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, scalar_min_max_sub(dst_reg, &src_reg); dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg.var_off); break; + case BPF_NEG: + env->fake_reg[0] = *dst_reg; + __mark_reg_known(dst_reg, 0); + scalar32_min_max_sub(dst_reg, &env->fake_reg[0]); + scalar_min_max_sub(dst_reg, &env->fake_reg[0]); + dst_reg->var_off = tnum_neg(env->fake_reg[0].var_off); + break; case BPF_MUL: dst_reg->var_off = tnum_mul(dst_reg->var_off, src_reg.var_off); scalar32_min_max_mul(dst_reg, &src_reg); @@ -15473,7 +15481,14 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) } /* check dest operand */ - err = check_reg_arg(env, insn->dst_reg, DST_OP); + if (opcode == BPF_NEG) { + err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK); + err = err ?: adjust_scalar_min_max_vals(env, insn, + ®s[insn->dst_reg], + regs[insn->dst_reg]); + } else { + err = check_reg_arg(env, insn->dst_reg, DST_OP); + } if (err) return err; |
