Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf bpf: Avoid memory leak from perf_env__insert_btf()

perf_env__insert_btf() doesn't insert if a duplicate BTF id is
encountered and this causes a memory leak. Modify the function to return
a success/error value and then free the memory if insertion didn't
happen.

v2. Adds a return -1 when the insertion error occurs in
perf_env__fetch_btf. This doesn't affect anything as the result is
never checked.

Fixes: 3792cb2ff43b1b19 ("perf bpf: Save BTF in a rbtree in perf_env")
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: KP Singh <kpsingh@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <songliubraving@fb.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: netdev@vger.kernel.org
Link: http://lore.kernel.org/lkml/20211112074525.121633-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
4924b1f7 4f74f187

+10 -3
+5 -1
tools/perf/util/bpf-event.c
··· 119 119 node->data_size = data_size; 120 120 memcpy(node->data, data, data_size); 121 121 122 - perf_env__insert_btf(env, node); 122 + if (!perf_env__insert_btf(env, node)) { 123 + /* Insertion failed because of a duplicate. */ 124 + free(node); 125 + return -1; 126 + } 123 127 return 0; 124 128 } 125 129
+4 -1
tools/perf/util/env.c
··· 75 75 return node; 76 76 } 77 77 78 - void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) 78 + bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) 79 79 { 80 80 struct rb_node *parent = NULL; 81 81 __u32 btf_id = btf_node->id; 82 82 struct btf_node *node; 83 83 struct rb_node **p; 84 + bool ret = true; 84 85 85 86 down_write(&env->bpf_progs.lock); 86 87 p = &env->bpf_progs.btfs.rb_node; ··· 95 94 p = &(*p)->rb_right; 96 95 } else { 97 96 pr_debug("duplicated btf %u\n", btf_id); 97 + ret = false; 98 98 goto out; 99 99 } 100 100 } ··· 105 103 env->bpf_progs.btfs_cnt++; 106 104 out: 107 105 up_write(&env->bpf_progs.lock); 106 + return ret; 108 107 } 109 108 110 109 struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
+1 -1
tools/perf/util/env.h
··· 167 167 struct bpf_prog_info_node *info_node); 168 168 struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, 169 169 __u32 prog_id); 170 - void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); 170 + bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); 171 171 struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id); 172 172 173 173 int perf_env__numa_node(struct perf_env *env, int cpu);