Skip to content

Commit c5ef534

Browse files
Amery HungAlexei Starovoitov
authored andcommitted
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 <[email protected]> Acked-by: Hou Tao <[email protected]> Signed-off-by: Amery Hung <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent f727b13 commit c5ef534

File tree

2 files changed

+5
-3
lines changed

2 files changed

+5
-3
lines changed

kernel/bpf/btf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3754,6 +3754,7 @@ static int btf_find_field(const struct btf *btf, const struct btf_type *t,
37543754
return -EINVAL;
37553755
}
37563756

3757+
/* Callers have to ensure the life cycle of btf if it is program BTF */
37573758
static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
37583759
struct btf_field_info *info)
37593760
{
@@ -3782,7 +3783,6 @@ static int btf_parse_kptr(const struct btf *btf, struct btf_field *field,
37823783
field->kptr.dtor = NULL;
37833784
id = info->kptr.type_id;
37843785
kptr_btf = (struct btf *)btf;
3785-
btf_get(kptr_btf);
37863786
goto found_dtor;
37873787
}
37883788
if (id < 0)

kernel/bpf/syscall.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,8 @@ void btf_record_free(struct btf_record *rec)
550550
case BPF_KPTR_PERCPU:
551551
if (rec->fields[i].kptr.module)
552552
module_put(rec->fields[i].kptr.module);
553-
btf_put(rec->fields[i].kptr.btf);
553+
if (btf_is_kernel(rec->fields[i].kptr.btf))
554+
btf_put(rec->fields[i].kptr.btf);
554555
break;
555556
case BPF_LIST_HEAD:
556557
case BPF_LIST_NODE:
@@ -596,7 +597,8 @@ struct btf_record *btf_record_dup(const struct btf_record *rec)
596597
case BPF_KPTR_UNREF:
597598
case BPF_KPTR_REF:
598599
case BPF_KPTR_PERCPU:
599-
btf_get(fields[i].kptr.btf);
600+
if (btf_is_kernel(fields[i].kptr.btf))
601+
btf_get(fields[i].kptr.btf);
600602
if (fields[i].kptr.module && !try_module_get(fields[i].kptr.module)) {
601603
ret = -ENXIO;
602604
goto free;

0 commit comments

Comments
 (0)