Re: [PATCH bpf-next 4/6] bpf, arm64: Fix exception table metadata for arena load-acquire
Puranjay Mohan <[email protected]>
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <CANk7y0hVZoGJRt=v=3499ALtJ5DnPA16OZYyEzBik=H-4G8+2g@mail.gmail.com> |
On Thu, Aug 6, 2026 at 3:39 PM Daniel Borkmann <[email protected]> wrote: > > Same problem as on x86-64: add_exception_handler() decides whether an > instruction is a load by its class, and a load-acquire is of BPF_STX > class even though it reads from src_reg into dst_reg. As a result ... > > if (BPF_CLASS(insn->code) != BPF_LDX) > dst_reg = DONT_CLEAR; > > ... drops the register to clear, and ... > > if (BPF_CLASS(insn->code) == BPF_LDX) > arena_reg = bpf2a64[insn->src_reg]; > else > arena_reg = bpf2a64[insn->dst_reg]; > > ... hands ex_handler_bpf() the value register instead of the address > register. A load-acquire from an arena pointer that faults on an > unmapped page is therefore reported as a WRITE at a bogus address, > and dst_reg keeps its previous value instead of being cleared to 0. > > Note that emit_atomic_ld_st() already picks src_reg as the address > for BPF_LOAD_ACQ, so only the exception table metadata was out of sync > with the emitted access. > > Same as on x86-64, use bpf_atomic_is_load_acq() so a load-acquire takes > the load path. > > Fixes: 9bb12368d539 ("bpf, arm64: Support load-acquire and store-release instructions") > Signed-off-by: Daniel Borkmann <[email protected]> > Cc: Peilin Ye <[email protected]> > --- > arch/arm64/net/bpf_jit_comp.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > > diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c > index 4cdc7dfb05ba..d14d297ebb96 100644 > --- a/arch/arm64/net/bpf_jit_comp.c > +++ b/arch/arm64/net/bpf_jit_comp.c > @@ -1178,7 +1178,12 @@ static int add_exception_handler(const struct bpf_insn *insn, > > ex->insn = ins_offset; > > - if (BPF_CLASS(insn->code) != BPF_LDX) > + /* > + * A load-acquire is of BPF_STX class, but reads from src_reg into > + * dst_reg like a BPF_LDX does, hence it must not be treated as a store > + * here. > + */ > + if (BPF_CLASS(insn->code) != BPF_LDX && !bpf_atomic_is_load_acq(insn)) > dst_reg = DONT_CLEAR; > > ex->fixup = FIELD_PREP(BPF_FIXUP_REG_MASK, dst_reg); > @@ -1193,7 +1198,7 @@ static int add_exception_handler(const struct bpf_insn *insn, > * memory access. Pass the reg holding the unmodified 32-bit address to > * ex_handler_bpf. > */ > - if (BPF_CLASS(insn->code) == BPF_LDX) > + if (BPF_CLASS(insn->code) == BPF_LDX || bpf_atomic_is_load_acq(insn)) > arena_reg = bpf2a64[insn->src_reg]; > else > arena_reg = bpf2a64[insn->dst_reg]; > -- > 2.43.0 > Thanks for fixing this. Reviewed-by: Puranjay Mohan <[email protected]>