Re: [PATCH bpf-next v4 05/12] bpf: Refactor object relationship tracking and fix dynptr UAF bug

Amery Hung <[email protected]> Thu, 7 May 2026 14:52:49 +0200
Newsgroups dev.linux.lists.sashiko,org.kernel.vger.bpf
Message-ID <CAMB2axO5ubguhhGTVRZ60odvHLHgyc+YggeiD8Fe7KDyP32YfA@mail.gmail.com>
On Wed, May 6, 2026 at 10:54 PM <[email protected]> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Critical] Dynptrs constructed from referenced objects are assigned a `parent_id` of 0, breaking cascading invalidation and leading to Use-After-Free.
> --
>
> commit 5c82adaba693d44fcc105cb9d8d86e76a67e2a64
> Author: Amery Hung <[email protected]>
>
> bpf: Refactor object relationship tracking and fix dynptr UAF bug
>
> This commit refactors verifier object relationship tracking by replacing
> the PTR_TO_MEM-specific dynptr_id with a general parent_id in bpf_reg_state.
> It updates release_reference() to use a DFS approach for cascading
> invalidation when parent objects are freed.
>
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> [ ... ]
> > @@ -11804,15 +11810,10 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
> >                               }
> >
> >                               dynptr_arg_type |= (unsigned int)get_dynptr_type_flag(parent_type);
> >                       }
> >
> >                       ret = process_dynptr_func(env, reg, argno, insn_idx, dynptr_arg_type,
> > -                                               clone_ref_obj_id, &meta->dynptr);
> > +                                               meta->ref_obj_id ? meta->id : 0, &meta->dynptr);
>
> Does this code assign 0 to the dynptr's parent_id instead of the actual
> parent's ID?

Yes. In this case, the parent is not a referenced object, so tracking
is unnecessary.

While we can track parent_id unconditionally, we should avoid doing it
now until every obj, referenced or not, has an id. Otherwise, it
becomes hard to reason where the parent_id is valid or not.

I will clarify this in parent_id's comment:
parent_id is only tracked when the parent object is referenced or is dynptr.

Although for a slice derived from a non-referenced dynptr, we don't
need to track the parent (allowing it to be accessed even when the
dynptr stack slot is destroyed). The slice should be destroyed when
the parent dynptr is destroyed in the dyntpr's mental model.

>
> For referenced objects acquired with PTR_MAYBE_NULL, the BPF program must
> perform a NULL check before passing the pointer to the constructor. Upon a
> successful NULL check, the verifier clears reg->id to 0 while preserving
> reg->ref_obj_id.

Not any more. See patch 4. Hence the following comments can be ignored.

>
> Consequently, meta->id appears to be unconditionally 0 when the dynptr is
> constructed here.
>
> When the parent object is subsequently released, the DFS traversal in
> release_reference() searches for descendants matching reg->parent_id == id.
> Because the dynptr's parent_id was initialized to 0, does this cause the
> dynptr to evade invalidation and remain fully active, leading to a
> use-after-free regression?
>
> Should this pass meta->ref_obj_id instead of meta->id?
>
> >                       if (ret < 0)
> >                               return ret;
> >                       break;
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5