bpf: Let callers of btf_parse_kptr() track life cycle of prog btf
btf_parse_kptr() and btf_record_free() do btf_get() and btf_put() respectively when working on btf_record in program and map if there are kptr fields. If the kptr is from program BTF, since both callers has already tracked the life cycle of program BTF, it is safe to remove the btf_get() and btf_put(). This change prevents memory leak of program BTF later when we start searching for kptr fields when building btf_record for program. It can happen when the btf fd is closed. The btf_put() corresponding to the btf_get() in btf_parse_kptr() was supposed to be called by btf_record_free() in btf_free_struct_meta_tab() in btf_free(). However, it will never happen since the invocation of btf_free() depends on the refcount of the btf to become 0 in the first place. Acked-by: Martin KaFai Lau <martin.lau@kernel.org> Acked-by: Hou Tao <houtao1@huawei.com> Signed-off-by: Amery Hung <amery.hung@bytedance.com> Link: https://lore.kernel.org/r/20240813212424.2871455-2-amery.hung@bytedance.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
f727b13dbe
commit
c5ef53420f
@ -3754,6 +3754,7 @@ static int btf_find_field(const struct btf *btf, const struct btf_type *t,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Callers have to ensure the life cycle of btf if it is program BTF */
|
||||
static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
|
||||
struct btf_field_info *info)
|
||||
{
|
||||
@ -3782,7 +3783,6 @@ static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
|
||||
field->kptr.dtor = NULL;
|
||||
id = info->kptr.type_id;
|
||||
kptr_btf = (struct btf *)btf;
|
||||
btf_get(kptr_btf);
|
||||
goto found_dtor;
|
||||
}
|
||||
if (id < 0)
|
||||
|
@ -550,7 +550,8 @@ void btf_record_free(struct btf_record *rec)
|
||||
case BPF_KPTR_PERCPU:
|
||||
if (rec->fields[i].kptr.module)
|
||||
module_put(rec->fields[i].kptr.module);
|
||||
btf_put(rec->fields[i].kptr.btf);
|
||||
if (btf_is_kernel(rec->fields[i].kptr.btf))
|
||||
btf_put(rec->fields[i].kptr.btf);
|
||||
break;
|
||||
case BPF_LIST_HEAD:
|
||||
case BPF_LIST_NODE:
|
||||
@ -596,7 +597,8 @@ struct btf_record *btf_record_dup(const struct btf_record *rec)
|
||||
case BPF_KPTR_UNREF:
|
||||
case BPF_KPTR_REF:
|
||||
case BPF_KPTR_PERCPU:
|
||||
btf_get(fields[i].kptr.btf);
|
||||
if (btf_is_kernel(fields[i].kptr.btf))
|
||||
btf_get(fields[i].kptr.btf);
|
||||
if (fields[i].kptr.module && !try_module_get(fields[i].kptr.module)) {
|
||||
ret = -ENXIO;
|
||||
goto free;
|
||||
|
Loading…
Reference in New Issue
Block a user