perf tools: Use list_del_init() more thorougly

To allow for destructors to check if they're operating on a object still
in a list, and to avoid going from use after free list entries into
still valid, or even also other already removed from list entries.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lkml.kernel.org/n/tip-deh17ub44atyox3j90e6rksu@git.kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d8f9da24
......@@ -431,7 +431,7 @@ static void delete_filter_func(struct list_head *head)
struct filter_entry *pos, *tmp;
list_for_each_entry_safe(pos, tmp, head, list) {
list_del(&pos->list);
list_del_init(&pos->list);
free(pos);
}
}
......
......@@ -454,7 +454,7 @@ static int report_lock_acquire_event(struct perf_evsel *evsel,
/* broken lock sequence, discard it */
ls->discard = 1;
bad_hist[BROKEN_ACQUIRE]++;
list_del(&seq->list);
list_del_init(&seq->list);
free(seq);
goto end;
default:
......@@ -515,7 +515,7 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
/* broken lock sequence, discard it */
ls->discard = 1;
bad_hist[BROKEN_ACQUIRED]++;
list_del(&seq->list);
list_del_init(&seq->list);
free(seq);
goto end;
default:
......@@ -570,7 +570,7 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
/* broken lock sequence, discard it */
ls->discard = 1;
bad_hist[BROKEN_CONTENDED]++;
list_del(&seq->list);
list_del_init(&seq->list);
free(seq);
goto end;
default:
......@@ -639,7 +639,7 @@ static int report_lock_release_event(struct perf_evsel *evsel,
ls->nr_release++;
free_seq:
list_del(&seq->list);
list_del_init(&seq->list);
free(seq);
end:
return 0;
......
......@@ -407,7 +407,7 @@ static void free_arch_std_events(void)
list_for_each_entry_safe(es, next, &arch_std_events, list) {
FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
list_del(&es->list);
list_del_init(&es->list);
free(es);
}
}
......
......@@ -238,7 +238,7 @@ static void free_event_nodes(struct list_head *events)
while (!list_empty(events)) {
node = list_entry(events->next, struct event_node, list);
list_del(&node->list);
list_del_init(&node->list);
free(node);
}
}
......
......@@ -152,7 +152,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
gtk_container_add(GTK_CONTAINER(window), view);
list_for_each_entry_safe(pos, n, &notes->src->source, al.node) {
list_del(&pos->al.node);
list_del_init(&pos->al.node);
disasm_line__free(pos);
}
......
......@@ -1586,7 +1586,7 @@ static void delete_last_nop(struct symbol *sym)
return;
}
list_del(&dl->al.node);
list_del_init(&dl->al.node);
disasm_line__free(dl);
}
}
......@@ -2463,7 +2463,7 @@ void annotated_source__purge(struct annotated_source *as)
struct annotation_line *al, *n;
list_for_each_entry_safe(al, n, &as->source, node) {
list_del(&al->node);
list_del_init(&al->node);
disasm_line__free(disasm_line(al));
}
}
......
......@@ -408,7 +408,7 @@ void auxtrace_queues__free(struct auxtrace_queues *queues)
buffer = list_entry(queues->queue_array[i].head.next,
struct auxtrace_buffer, list);
list_del(&buffer->list);
list_del_init(&buffer->list);
auxtrace_buffer__free(buffer);
}
}
......@@ -612,7 +612,7 @@ void auxtrace_index__free(struct list_head *head)
struct auxtrace_index *auxtrace_index, *n;
list_for_each_entry_safe(auxtrace_index, n, head, list) {
list_del(&auxtrace_index->list);
list_del_init(&auxtrace_index->list);
free(auxtrace_index);
}
}
......
......@@ -829,7 +829,7 @@ static void
bpf_map_op__delete(struct bpf_map_op *op)
{
if (!list_empty(&op->list))
list_del(&op->list);
list_del_init(&op->list);
if (op->key_type == BPF_MAP_KEY_RANGES)
parse_events__clear_array(&op->k.array);
free(op);
......
......@@ -40,7 +40,7 @@ void call_path_root__free(struct call_path_root *cpr)
struct call_path_block *pos, *n;
list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
list_del(&pos->node);
list_del_init(&pos->node);
free(pos);
}
free(cpr);
......
......@@ -636,7 +636,7 @@ add_child(struct callchain_node *parent,
struct callchain_list *call, *tmp;
list_for_each_entry_safe(call, tmp, &new->val, list) {
list_del(&call->list);
list_del_init(&call->list);
map__zput(call->ms.map);
free(call);
}
......@@ -1002,7 +1002,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
callchain_cursor_append(cursor, list->ip,
list->ms.map, list->ms.sym,
false, NULL, 0, 0, 0, list->srcline);
list_del(&list->list);
list_del_init(&list->list);
map__zput(list->ms.map);
free(list);
}
......@@ -1453,13 +1453,13 @@ static void free_callchain_node(struct callchain_node *node)
struct rb_node *n;
list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
list_del(&list->list);
list_del_init(&list->list);
map__zput(list->ms.map);
free(list);
}
list_for_each_entry_safe(list, tmp, &node->val, list) {
list_del(&list->list);
list_del_init(&list->list);
map__zput(list->ms.map);
free(list);
}
......@@ -1544,7 +1544,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
out:
list_for_each_entry_safe(chain, new, &head, list) {
list_del(&chain->list);
list_del_init(&chain->list);
map__zput(chain->ms.map);
free(chain);
}
......
......@@ -34,7 +34,7 @@ static int db_export__deferred(struct db_export *dbe)
de = list_entry(dbe->deferred.next, struct deferred_export,
node);
err = dbe->export_comm(dbe, de->comm);
list_del(&de->node);
list_del_init(&de->node);
free(de);
if (err)
return err;
......@@ -50,7 +50,7 @@ static void db_export__free_deferred(struct db_export *dbe)
while (!list_empty(&dbe->deferred)) {
de = list_entry(dbe->deferred.next, struct deferred_export,
node);
list_del(&de->node);
list_del_init(&de->node);
free(de);
}
}
......
......@@ -434,7 +434,7 @@ static void dso__list_add(struct dso *dso)
static void dso__list_del(struct dso *dso)
{
list_del(&dso->data.open_entry);
list_del_init(&dso->data.open_entry);
WARN_ONCE(dso__data_open_cnt <= 0,
"DSO data fd counter out of bounds.");
dso__data_open_cnt--;
......
......@@ -1298,7 +1298,7 @@ static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
struct perf_evsel_config_term *term, *h;
list_for_each_entry_safe(term, h, &evsel->config_terms, list) {
list_del(&term->list);
list_del_init(&term->list);
free(term);
}
}
......
......@@ -2741,10 +2741,10 @@ static void hists_evsel__exit(struct perf_evsel *evsel)
list_for_each_entry_safe(node, tmp, &hists->hpp_formats, list) {
perf_hpp_list__for_each_format_safe(&node->hpp, fmt, pos) {
list_del(&fmt->list);
list_del_init(&fmt->list);
free(fmt);
}
list_del(&node->list);
list_del_init(&node->list);
free(node);
}
}
......
......@@ -138,7 +138,7 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
if (!list_empty(cache)) {
new = list_entry(cache->next, struct ordered_event, list);
list_del(&new->list);
list_del_init(&new->list);
} else if (oe->buffer) {
new = &oe->buffer->event[oe->buffer_idx];
if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
......@@ -394,13 +394,13 @@ void ordered_events__free(struct ordered_events *oe)
* yet, we need to free only allocated ones ...
*/
if (oe->buffer) {
list_del(&oe->buffer->list);
list_del_init(&oe->buffer->list);
ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
}
/* ... and continue with the rest */
list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
list_del(&buffer->list);
list_del_init(&buffer->list);
ordered_events_buffer__free(buffer, MAX_SAMPLE_BUFFER, oe);
}
}
......
......@@ -652,7 +652,7 @@ static int add_bpf_event(const char *group, const char *event, int fd,
pr_debug("Failed to add BPF event %s:%s\n",
group, event);
list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
list_del(&evsel->node);
list_del_init(&evsel->node);
perf_evsel__delete(evsel);
}
return err;
......
......@@ -1245,7 +1245,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
info->metric_expr = alias->metric_expr;
info->metric_name = alias->metric_name;
list_del(&term->list);
list_del_init(&term->list);
free(term);
}
......
......@@ -2333,7 +2333,7 @@ static void kprobe_blacklist__delete(struct list_head *blacklist)
while (!list_empty(blacklist)) {
node = list_first_entry(blacklist,
struct kprobe_blacklist_node, list);
list_del(&node->list);
list_del_init(&node->list);
zfree(&node->symbol);
free(node);
}
......
......@@ -756,7 +756,7 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
*/
if (err) {
sfq->buffer = NULL;
list_del(&buffer->list);
list_del_init(&buffer->list);
auxtrace_buffer__free(buffer);
if (err > 0) /* Buffer done, no error */
err = 0;
......
......@@ -83,7 +83,7 @@ static void fill_lines(char **lines, int maxline, char *map, int maplen)
static void free_srcfile(struct srcfile *sf)
{
list_del(&sf->nd);
list_del_init(&sf->nd);
hlist_del(&sf->hash_nd);
map_total_sz -= sf->maplen;
munmap(sf->map, sf->maplen);
......
......@@ -1478,7 +1478,7 @@ static void kcore_copy__free_phdrs(struct kcore_copy_info *kci)
struct phdr_data *p, *tmp;
list_for_each_entry_safe(p, tmp, &kci->phdrs, node) {
list_del(&p->node);
list_del_init(&p->node);
free(p);
}
}
......@@ -1501,7 +1501,7 @@ static void kcore_copy__free_syms(struct kcore_copy_info *kci)
struct sym_data *s, *tmp;
list_for_each_entry_safe(s, tmp, &kci->syms, node) {
list_del(&s->node);
list_del_init(&s->node);
free(s);
}
}
......@@ -2252,7 +2252,7 @@ int cleanup_sdt_note_list(struct list_head *sdt_notes)
int nr_free = 0;
list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) {
list_del(&pos->note_list);
list_del_init(&pos->note_list);
zfree(&pos->name);
zfree(&pos->provider);
free(pos);
......
......@@ -93,14 +93,14 @@ void thread__delete(struct thread *thread)
down_write(&thread->namespaces_lock);
list_for_each_entry_safe(namespaces, tmp_namespaces,
&thread->namespaces_list, list) {
list_del(&namespaces->list);
list_del_init(&namespaces->list);
namespaces__free(namespaces);
}
up_write(&thread->namespaces_lock);
down_write(&thread->comm_lock);
list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) {
list_del(&comm->list);
list_del_init(&comm->list);
comm__free(comm);
}
up_write(&thread->comm_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment