Commit c5c1e313 authored by Ihor Solodrai's avatar Ihor Solodrai Committed by Alexei Starovoitov
Browse files

resolve_btfids: Fix memory leaks reported by ASAN



Running resolve_btfids with ASAN reveals memory leaks in btf_id
handling.

- Change get_id() to use a local buffer
- Make btf_id__add() strdup the name internally
- Add btf_id__free_all() that frees all nodese of a tree
- Call the cleanup function on exit for every tree

Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarIhor Solodrai <ihor.solodrai@linux.dev>
Link: https://lore.kernel.org/r/20260223190736.649171-8-ihor.solodrai@linux.dev


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 4021848a
Loading
Loading
Loading
Loading
+54 −27
Original line number Diff line number Diff line
@@ -226,7 +226,7 @@ static struct btf_id *btf_id__find(struct rb_root *root, const char *name)
}

static struct btf_id *__btf_id__add(struct rb_root *root,
				    char *name,
				    const char *name,
				    enum btf_id_kind kind,
				    bool unique)
{
@@ -250,7 +250,11 @@ static struct btf_id *__btf_id__add(struct rb_root *root,
	id = zalloc(sizeof(*id));
	if (id) {
		pr_debug("adding symbol %s\n", name);
		id->name = name;
		id->name = strdup(name);
		if (!id->name) {
			free(id);
			return NULL;
		}
		id->kind = kind;
		rb_link_node(&id->rb_node, parent, p);
		rb_insert_color(&id->rb_node, root);
@@ -258,17 +262,21 @@ static struct btf_id *__btf_id__add(struct rb_root *root,
	return id;
}

static inline struct btf_id *btf_id__add(struct rb_root *root, char *name, enum btf_id_kind kind)
static inline struct btf_id *btf_id__add(struct rb_root *root,
					 const char *name,
					 enum btf_id_kind kind)
{
	return __btf_id__add(root, name, kind, false);
}

static inline struct btf_id *btf_id__add_unique(struct rb_root *root, char *name, enum btf_id_kind kind)
static inline struct btf_id *btf_id__add_unique(struct rb_root *root,
						const char *name,
						enum btf_id_kind kind)
{
	return __btf_id__add(root, name, kind, true);
}

static char *get_id(const char *prefix_end)
static int get_id(const char *prefix_end, char *buf, size_t buf_sz)
{
	/*
	 * __BTF_ID__func__vfs_truncate__0
@@ -277,28 +285,28 @@ static char *get_id(const char *prefix_end)
	 */
	int len = strlen(prefix_end);
	int pos = sizeof("__") - 1;
	char *p, *id;
	char *p;

	if (pos >= len)
		return NULL;
		return -1;

	id = strdup(prefix_end + pos);
	if (id) {
	if (len - pos >= buf_sz)
		return -1;

	strcpy(buf, prefix_end + pos);
	/*
	 * __BTF_ID__func__vfs_truncate__0
		 * id =            ^
	 * buf =           ^
	 *
	 * cut the unique id part
	 */
		p = strrchr(id, '_');
	p = strrchr(buf, '_');
	p--;
		if (*p != '_') {
			free(id);
			return NULL;
		}
	if (*p != '_')
		return -1;
	*p = '\0';
	}
	return id;

	return 0;
}

static struct btf_id *add_set(struct object *obj, char *name, enum btf_id_kind kind)
@@ -335,10 +343,9 @@ static struct btf_id *add_set(struct object *obj, char *name, enum btf_id_kind k

static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size)
{
	char *id;
	char id[KSYM_NAME_LEN];

	id = get_id(name + size);
	if (!id) {
	if (get_id(name + size, id, sizeof(id))) {
		pr_err("FAILED to parse symbol name: %s\n", name);
		return NULL;
	}
@@ -346,6 +353,21 @@ static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size)
	return btf_id__add(root, id, BTF_ID_KIND_SYM);
}

static void btf_id__free_all(struct rb_root *root)
{
	struct rb_node *next;
	struct btf_id *id;

	next = rb_first(root);
	while (next) {
		id = rb_entry(next, struct btf_id, rb_node);
		next = rb_next(&id->rb_node);
		rb_erase(&id->rb_node, root);
		free(id->name);
		free(id);
	}
}

static void bswap_32_data(void *data, u32 nr_bytes)
{
	u32 cnt, i;
@@ -1547,6 +1569,11 @@ int main(int argc, const char **argv)
out:
	btf__free(obj.base_btf);
	btf__free(obj.btf);
	btf_id__free_all(&obj.structs);
	btf_id__free_all(&obj.unions);
	btf_id__free_all(&obj.typedefs);
	btf_id__free_all(&obj.funcs);
	btf_id__free_all(&obj.sets);
	if (obj.efile.elf) {
		elf_end(obj.efile.elf);
		close(obj.efile.fd);