In check_alu_op(), the verifier currently calls check_reg_arg() and
adjust_scalar_min_max_vals() unconditionally for BPF_NEG operations.
However, if the destination register holds a pointer, these scalar
adjustments are unnecessary and potentially incorrect.
This patch adds a check to skip the adjustment logic when the destination
register contains a pointer.
Reported-by: syzbot+d36d5ae81e1b0a53ef58@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
Fixes: aced132599b3 ("bpf: Add range tracking for BPF_NEG")
Suggested-by: KaFai Wan <kafai.wan@linux.dev>
Signed-off-by: Brahmajit Das <listout@listout.xyz>
---
kernel/bpf/verifier.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e892df386eed..4b0924c38657 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -15645,7 +15645,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
}
/* check dest operand */
- if (opcode == BPF_NEG) {
+ if (opcode == BPF_NEG &&
+ !__is_pointer_value(false, ®s[insn->dst_reg])) {
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],
--
2.51.0
On Wed, 2025-10-01 at 15:26 +0530, Brahmajit Das wrote:
> In check_alu_op(), the verifier currently calls check_reg_arg() and
> adjust_scalar_min_max_vals() unconditionally for BPF_NEG operations.
> However, if the destination register holds a pointer, these scalar
> adjustments are unnecessary and potentially incorrect.
>
> This patch adds a check to skip the adjustment logic when the destination
> register contains a pointer.
>
> Reported-by: syzbot+d36d5ae81e1b0a53ef58@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
> Fixes: aced132599b3 ("bpf: Add range tracking for BPF_NEG")
> Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> Signed-off-by: Brahmajit Das <listout@listout.xyz>
> ---
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
> kernel/bpf/verifier.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index e892df386eed..4b0924c38657 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -15645,7 +15645,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
> }
>
> /* check dest operand */
> - if (opcode == BPF_NEG) {
> + if (opcode == BPF_NEG &&
> + !__is_pointer_value(false, ®s[insn->dst_reg])) {
Nit: I'd made this a bit simpler: `regs[insn->dst_reg].type == SCALAR_VALUE`,
instead of __is_pointer_value() call.
> 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],
On 01.10.2025 11:29, Eduard Zingerman wrote:
> On Wed, 2025-10-01 at 15:26 +0530, Brahmajit Das wrote:
> > In check_alu_op(), the verifier currently calls check_reg_arg() and
> > adjust_scalar_min_max_vals() unconditionally for BPF_NEG operations.
> > However, if the destination register holds a pointer, these scalar
> > adjustments are unnecessary and potentially incorrect.
> >
> > This patch adds a check to skip the adjustment logic when the destination
> > register contains a pointer.
> >
> > Reported-by: syzbot+d36d5ae81e1b0a53ef58@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
> > Fixes: aced132599b3 ("bpf: Add range tracking for BPF_NEG")
> > Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> > Signed-off-by: Brahmajit Das <listout@listout.xyz>
> > ---
>
> Acked-by: Eduard Zingerman <eddyz87@gmail.com>
>
Thanks
>
> Nit: I'd made this a bit simpler: `regs[insn->dst_reg].type == SCALAR_VALUE`,
> instead of __is_pointer_value() call.
>
> > 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],
Do I need to send a v4?
--
Regards,
listout
On Thu, 2025-10-02 at 00:19 +0530, Brahmajit Das wrote:
> On 01.10.2025 11:29, Eduard Zingerman wrote:
> > On Wed, 2025-10-01 at 15:26 +0530, Brahmajit Das wrote:
> > > In check_alu_op(), the verifier currently calls check_reg_arg() and
> > > adjust_scalar_min_max_vals() unconditionally for BPF_NEG operations.
> > > However, if the destination register holds a pointer, these scalar
> > > adjustments are unnecessary and potentially incorrect.
> > >
> > > This patch adds a check to skip the adjustment logic when the destination
> > > register contains a pointer.
> > >
> > > Reported-by: syzbot+d36d5ae81e1b0a53ef58@syzkaller.appspotmail.com
> > > Closes: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
> > > Fixes: aced132599b3 ("bpf: Add range tracking for BPF_NEG")
> > > Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> > > Signed-off-by: Brahmajit Das <listout@listout.xyz>
> > > ---
> >
> > Acked-by: Eduard Zingerman <eddyz87@gmail.com>
> >
> Thanks
> >
> > Nit: I'd made this a bit simpler: `regs[insn->dst_reg].type == SCALAR_VALUE`,
> > instead of __is_pointer_value() call.
> >
> > > 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],
> Do I need to send a v4?
As you see fit.
If you agree with my suggestion, please send v4,
leaving it as-is also fine by me.
On Wed, Oct 1, 2025 at 2:56 AM Brahmajit Das <listout@listout.xyz> wrote:
>
> In check_alu_op(), the verifier currently calls check_reg_arg() and
> adjust_scalar_min_max_vals() unconditionally for BPF_NEG operations.
> However, if the destination register holds a pointer, these scalar
> adjustments are unnecessary and potentially incorrect.
>
> This patch adds a check to skip the adjustment logic when the destination
> register contains a pointer.
>
> Reported-by: syzbot+d36d5ae81e1b0a53ef58@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
> Fixes: aced132599b3 ("bpf: Add range tracking for BPF_NEG")
> Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> Signed-off-by: Brahmajit Das <listout@listout.xyz>
> ---
> kernel/bpf/verifier.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index e892df386eed..4b0924c38657 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -15645,7 +15645,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
> }
>
> /* check dest operand */
> - if (opcode == BPF_NEG) {
> + if (opcode == BPF_NEG &&
> + !__is_pointer_value(false, ®s[insn->dst_reg])) {
> err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
The fix makes sense.
Song,
Eduard,
please take a look.
© 2016 - 2025 Red Hat, Inc.