]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
resolve_btfids: Fix memory leaks reported by ASAN
authorIhor Solodrai <ihor.solodrai@linux.dev>
Mon, 23 Feb 2026 19:07:23 +0000 (11:07 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 24 Feb 2026 16:19:49 +0000 (08:19 -0800)
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: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Link: https://lore.kernel.org/r/20260223190736.649171-8-ihor.solodrai@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/bpf/resolve_btfids/main.c

index ca7fcd03efb6ea31b3b3b6ef1a960ac957f1cac4..5208f650080fe02b85b617e081c83fec5ef45ca6 100644 (file)
@@ -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) {
-               /*
-                * __BTF_ID__func__vfs_truncate__0
-                * id =            ^
-                *
-                * cut the unique id part
-                */
-               p = strrchr(id, '_');
-               p--;
-               if (*p != '_') {
-                       free(id);
-                       return NULL;
-               }
-               *p = '\0';
-       }
-       return id;
+       if (len - pos >= buf_sz)
+               return -1;
+
+       strcpy(buf, prefix_end + pos);
+       /*
+        * __BTF_ID__func__vfs_truncate__0
+        * buf =           ^
+        *
+        * cut the unique id part
+        */
+       p = strrchr(buf, '_');
+       p--;
+       if (*p != '_')
+               return -1;
+       *p = '\0';
+
+       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 @@ dump_btf:
 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);