Open-coded iterator next kfuncs that return non-struct pointers associate the returned PTR_TO_MEM with the iterator's reference ID. Struct pointer returns take a separate PTR_TO_BTF_ID path which omits this relationship. This leaves the pointer returned by bpf_iter_task_vma_next() valid in the verifier after bpf_iter_task_vma_destroy() frees the iterator's backing allocation, including the VMA snapshot. A BPF program can therefore read the released snapshot through the stale pointer. Set the iterator reference ID as the parent of non-RCU PTR_TO_BTF_ID results from iterator next kfuncs. Releasing the iterator reference in the destructor then invalidates those results as it already does for PTR_TO_MEM results. Leave MEM_RCU results unchanged. Their lifetime is independently protected by the surrounding RCU read-side critical section, which can remain active after an iterator is destroyed. This issue was found during BPF verifier testing with an in-house runtime semantic checker. Fixes: 4cbee026db54 ("bpf: return VMA snapshot from task_vma iterator") Assisted-by: LLM Signed-off-by: Xu Yunxiang --- kernel/bpf/verifier.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 72a3f5998dd27..be4978629ae59 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -14105,6 +14105,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, regs[BPF_REG_0].btf = desc_btf; regs[BPF_REG_0].type = type; regs[BPF_REG_0].btf_id = ptr_type_id; + + if (bpf_is_iter_next_kfunc(&meta) && !(type & MEM_RCU)) + regs[BPF_REG_0].parent_id = meta.ref_obj.id; } if (is_kfunc_ret_null(&meta)) { -- 2.43.0