libbpf: Fix use-after-free in btf_dump_name_dups
[platform/kernel/linux-starfive.git] / tools / lib / bpf / btf_dump.c
index 3937f66..0b47016 100644 (file)
@@ -219,6 +219,17 @@ static int btf_dump_resize(struct btf_dump *d)
        return 0;
 }
 
+static void btf_dump_free_names(struct hashmap *map)
+{
+       size_t bkt;
+       struct hashmap_entry *cur;
+
+       hashmap__for_each_entry(map, cur, bkt)
+               free((void *)cur->key);
+
+       hashmap__free(map);
+}
+
 void btf_dump__free(struct btf_dump *d)
 {
        int i;
@@ -237,8 +248,8 @@ void btf_dump__free(struct btf_dump *d)
        free(d->cached_names);
        free(d->emit_queue);
        free(d->decl_stack);
-       hashmap__free(d->type_names);
-       hashmap__free(d->ident_names);
+       btf_dump_free_names(d->type_names);
+       btf_dump_free_names(d->ident_names);
 
        free(d);
 }
@@ -1520,11 +1531,23 @@ static void btf_dump_emit_type_cast(struct btf_dump *d, __u32 id,
 static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map,
                                 const char *orig_name)
 {
+       char *old_name, *new_name;
        size_t dup_cnt = 0;
+       int err;
+
+       new_name = strdup(orig_name);
+       if (!new_name)
+               return 1;
 
        hashmap__find(name_map, orig_name, (void **)&dup_cnt);
        dup_cnt++;
-       hashmap__set(name_map, orig_name, (void *)dup_cnt, NULL, NULL);
+
+       err = hashmap__set(name_map, new_name, (void *)dup_cnt,
+                          (const void **)&old_name, NULL);
+       if (err)
+               free(new_name);
+
+       free(old_name);
 
        return dup_cnt;
 }