public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
From: Puranjay Mohan <puranjay@kernel.org>
To: Daniel Borkmann <daniel@iogearbox.net>, eddyz87@gmail.com
Cc: ast@kernel.org, bpf@vger.kernel.org, STAR Labs SG <info@starlabs.sg>
Subject: Re: [PATCH bpf 1/2] bpf: Fix incorrect pruning due to atomic fetch precision tracking
Date: Mon, 30 Mar 2026 15:41:14 +0100	[thread overview]
Message-ID: <m2o6k5z8fp.fsf@kernel.org> (raw)
In-Reply-To: <20260330132750.377862-1-daniel@iogearbox.net>

Daniel Borkmann <daniel@iogearbox.net> writes:

> When backtrack_insn encounters a BPF_STX instruction with BPF_ATOMIC
> and BPF_FETCH, the src register (or r0 for BPF_CMPXCHG) also acts as
> a destination, thus receiving the old value from the memory location.
>
> The current backtracking logic does not account for this. It treats
> atomic fetch operations the same as regular stores where the src
> register is only an input. This leads the backtrack_insn to fail to
> propagate precision to the stack location, which is then not marked
> as precise!
>
> Later, the verifier's path pruning can incorrectly consider two states
> equivalent when they differ in terms of stack state. Meaning, two
> branches can be treated as equivalent and thus get pruned when they
> should not be seen as such.
>
> Fix it as follows: When the fetch dst register is being tracked for
> precision, clear it and propagate precision over to the stack slot.
> This is similar to how BPF_LDX handles loads from the stack.
>
> Before:
>
>   0: (b7) r1 = 8                        ; R1=8
>   1: (7b) *(u64 *)(r10 -8) = r1         ; R1=8 R10=fp0 fp-8=8
>   2: (b7) r2 = 0                        ; R2=0
>   3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2)          ; R2=8 R10=fp0 fp-8=mmmmmmmm
>   4: (bf) r3 = r10                      ; R3=fp0 R10=fp0
>   5: (0f) r3 += r2
>   mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
>   mark_precise: frame0: regs=r2 stack= before 4: (bf) r3 = r10
>   mark_precise: frame0: regs=r2 stack= before 3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2)
>   mark_precise: frame0: regs=r2 stack= before 2: (b7) r2 = 0
>   6: R2=8 R3=fp8
>   6: (b7) r0 = 0                        ; R0=0
>   7: (95) exit
>
> After:
>
>   0: (b7) r1 = 8                        ; R1=8
>   1: (7b) *(u64 *)(r10 -8) = r1         ; R1=8 R10=fp0 fp-8=8
>   2: (b7) r2 = 0                        ; R2=0
>   3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2)          ; R2=8 R10=fp0 fp-8=mmmmmmmm
>   4: (bf) r3 = r10                      ; R3=fp0 R10=fp0
>   5: (0f) r3 += r2
>   mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
>   mark_precise: frame0: regs=r2 stack= before 4: (bf) r3 = r10
>   mark_precise: frame0: regs=r2 stack= before 3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2)
>   mark_precise: frame0: regs= stack=-8 before 2: (b7) r2 = 0
>   mark_precise: frame0: regs= stack=-8 before 1: (7b) *(u64 *)(r10 -8) = r1
>   mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8
>   6: R2=8 R3=fp8
>   6: (b7) r0 = 0                        ; R0=0
>   7: (95) exit
>
> Fixes: 5ffa25502b5a ("bpf: Add instructions for atomic_[cmp]xchg")
> Fixes: 5ca419f2864a ("bpf: Add BPF_FETCH field / create atomic_fetch_add instruction")
> Reported-by: STAR Labs SG <info@starlabs.sg>
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

Athough not related to this patch but it made me think about how the
conditional semantics of CMPXCHG could interact with precision tracking,
because the CMPXCHG could write to a stack slot or not depending on the
comparison and that slot could later be used for precision tracking. But
I found that although check_atomic_rmw() set's INSN_F_STACK_ACCESS in
the flags, it also makes the stack slot STACK_MISC, therefore
instruction reading from it will not have INSN_F_STACK_ACCESS so the
precision tracking will stop there.

This patch looks correct to me.

Reviewed-by: Puranjay Mohan <puranjay@kernel.org>


> ---
>  kernel/bpf/verifier.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index f108c01ff6d0..293aa957a5ff 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -4474,6 +4474,31 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
>  			 * encountered a case of pointer subtraction.
>  			 */
>  			return -ENOTSUPP;
> +
> +		/* atomic fetch operation writes the old value into a
> +		 * register (sreg or r0) and if it was tracked for
> +		 * precision, propagate to the stack slot like we do
> +		 * in ldx.
> +		 */
> +		if (class == BPF_STX && mode == BPF_ATOMIC &&
> +		    (insn->imm & BPF_FETCH)) {
> +			u32 load_reg = insn->imm == BPF_CMPXCHG ?
> +				       BPF_REG_0 : sreg;
> +
> +			if (bt_is_reg_set(bt, load_reg)) {
> +				bt_clear_reg(bt, load_reg);
> +				/* atomic fetch from non-stack memory
> +				 * can't be further backtracked, same
> +				 * as for ldx.
> +				 */
> +				if (!hist || !(hist->flags & INSN_F_STACK_ACCESS))
> +					return 0;
> +				spi = insn_stack_access_spi(hist->flags);
> +				fr = insn_stack_access_frameno(hist->flags);
> +				bt_set_frame_slot(bt, fr, spi);
> +				return 0;
> +			}
> +		}
>  		/* scalars can only be spilled into stack */
>  		if (!hist || !(hist->flags & INSN_F_STACK_ACCESS))
>  			return 0;
> -- 
> 2.43.0

  parent reply	other threads:[~2026-03-30 14:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-30 13:27 [PATCH bpf 1/2] bpf: Fix incorrect pruning due to atomic fetch precision tracking Daniel Borkmann
2026-03-30 13:27 ` [PATCH bpf 2/2] selftests/bpf: Add more precision tracking tests for atomics Daniel Borkmann
2026-03-30 14:42   ` Puranjay Mohan
2026-03-30 14:41 ` Puranjay Mohan [this message]
2026-03-30 21:56   ` [PATCH bpf 1/2] bpf: Fix incorrect pruning due to atomic fetch precision tracking Daniel Borkmann
2026-03-30 14:45 ` Alexei Starovoitov
2026-03-30 22:02   ` Daniel Borkmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2o6k5z8fp.fsf@kernel.org \
    --to=puranjay@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=info@starlabs.sg \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox