On Mon Jun 15, 2026 at 10:57 AM CEST, Nuoqi Gui wrote:
> bpf_rdonly_cast() is an identity operation at runtime, but the verifier
> currently assigns the result fresh return-state metadata. When the source
> pointer comes from bpf_dynptr_slice(), that drops the relationship needed
> to invalidate the alias when the dynptr is released.
>
> Preserve the dynptr-slice lifetime metadata across bpf_rdonly_cast(), and
> add verifier selftests covering cases where a dynptr slice is cast and then
> read after the dynptr is released or after the originating dynptr stack slot
> is
> overwritten while a clone still holds the reference. Also cover the valid
> clone
> case where the cast alias is derived from the clone and remains usable after
> the original dynptr is overwritten.
>
> This fixes regressions introduced by 66e3a13e7c2c ("bpf: Add
> bpf_dynptr_slice and bpf_dynptr_slice_rdwr") and a35b9af4ec2c ("bpf: Add a
> kfunc for generic type cast").
>
> Impact is bounded to verifier lifetime tracking for CAP-required BPF
> programs. The evidence confirms stale read acceptance after dynptr release,
> including a typed field-read shape, but does not demonstrate unprivileged
> reachability, cross-context disclosure, controlled reuse, arbitrary kernel
> read, write-capable aliasing, privilege escalation, crash, or KASAN/UAF
> signal. No CVE, embargo, or security escalation is claimed.
>
> Validation:
> - The new dynptr_fail.c subtests exercise the verifier's dynptr-slice
> lifetime invariant across bpf_rdonly_cast(): a cast alias of a
> bpf_dynptr_slice() result must be invalidated when the dynptr is released or
> its stack slot overwritten, while a cast alias derived from a surviving
> clone
> must stay usable.
Won't fix. The semantics of bpf_rdonly_cast() do not require soruce provenance
tracking, and thus don't need any invalidation. It can take any unknown value
and produces safe to read pointer. Please try to reason about whether it's a
real issue before posting AI's output directly.
pw-bot: cr
> - Unpatched bpf at 76f62d237538: test_progs -t dynptr FAILs as expected,
> because the four __failure subtests
> (dynptr_rdonly_cast_{,typed_}slice_after_{release,overwrite}) are wrongly
> accepted - the stale read survives dynptr release.
> - Patched with this series: test_progs -t dynptr PASSes, because those four
> casts are now rejected with "invalid mem access 'scalar'" and the two
> __success clone subtests remain accepted (all six dynptr_rdonly_cast_*
> subtests OK, rc 0).
>
> Signed-off-by: Nuoqi Gui <[email protected]>
> ---
> Nuoqi Gui (2):
> bpf: Preserve dynptr slice lifetime across rdonly_cast
> selftests/bpf: Cover rdonly_cast dynptr slice lifetime
>
> include/linux/bpf_verifier.h | 5 +
> kernel/bpf/verifier.c | 36 ++++--
> tools/testing/selftests/bpf/progs/dynptr_fail.c | 160
> ++++++++++++++++++++++++
> 3 files changed, 193 insertions(+), 8 deletions(-)
> ---
> base-commit: 76f62d237538b456354a44e796a541cde03c6e28
> change-id: 20260615-f01-09-rdonly-cast-dynptr-lifetime-de114e5a1838
>
> Best regards,
> --
> Nuoqi Gui <[email protected]>