aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2025-06-25 15:12:18 -0700
committerAlexei Starovoitov <ast@kernel.org>2025-06-25 15:12:30 -0700
commit0967f5399b64aafb0bff1e76bca45446a3e1b6af (patch)
tree8ec7384fe76f8688d3bff5f7fbdbf9876f59d3ff /kernel
parentselftests/bpf: Fix usdt multispec failure with arm64/clang20 selftest build (diff)
parentselftests/bpf: Add tests for BPF_NEG range tracking logic (diff)
downloadlinux-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')
-rw-r--r--kernel/bpf/tnum.c5
-rw-r--r--kernel/bpf/verifier.c17
2 files changed, 21 insertions, 1 deletions
diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
index 9dbc31b25e3d..fa353c5d550f 100644
--- a/kernel/bpf/tnum.c
+++ b/kernel/bpf/tnum.c
@@ -83,6 +83,11 @@ struct tnum tnum_sub(struct tnum a, struct tnum b)
return TNUM(dv & ~mu, mu);
}
+struct tnum tnum_neg(struct tnum a)
+{
+ return tnum_sub(TNUM(0, 0), a);
+}
+
struct tnum tnum_and(struct tnum a, struct tnum b)
{
u64 alpha, beta, v;
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,
+ &regs[insn->dst_reg],
+ regs[insn->dst_reg]);
+ } else {
+ err = check_reg_arg(env, insn->dst_reg, DST_OP);
+ }
if (err)
return err;