A field in the __safe_trusted or __safe_trusted_or_null set walked out of a referenced parent yields PTR_TRUSTED with nothing tying it to the reference that keeps it alive. Releasing the parent invalidates the parent's own register but not the walked field, which stays fully trusted after the object may already be freed: file = bpf_get_task_exe_file(task); /* acquired */ inode = file->f_inode; /* __safe_trusted */ bpf_put_file(file); /* inode stays trusted */ Set the walked field's parent_id to the parent's reference id, or to the parent's own parent_id so a chain of derived fields stays bound to the original reference. release_reference() already invalidates every register whose parent_id matches, recursively, and regsafe() already maps parent_id through check_ids(), so no other verifier changes are needed. An RCU-protected parent keeps bounding its fields to the RCU critical section through MEM_RCU instead. Fixes: 6fcd486b3a0a ("bpf: Refactor RCU enforcement in the verifier.") Signed-off-by: Justin Suess --- kernel/bpf/verifier.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 20ca8591a0fe..8c39ec2ff408 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6562,6 +6562,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, const char *tname = btf_name_by_offset(reg->btf, t->name_off); const char *field_name = NULL; enum bpf_type_flag flag = 0; + u32 parent_id = 0; u32 btf_id = 0; s64 min_off; int ret; @@ -6716,6 +6717,11 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, */ flag = PTR_UNTRUSTED; } + + /* A trusted field is pinned by whatever pins its parent. */ + if (flag & PTR_TRUSTED) + parent_id = reg_is_referenced(env, reg) ? reg->id : + reg->parent_id; } else { /* Old compat. Deprecated */ clear_trusted_flags(&flag); @@ -6725,6 +6731,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, ret = mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag); if (ret < 0) return ret; + regs[value_regno].parent_id = parent_id; } return 0; -- 2.55.0