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.
- 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]>