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
next prev 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