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

perf tools: Use zfree to help detect use after free bugs

Several areas already used this technique, so do some audit to
consistently use it elsewhere.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-9sbere0kkplwe45ak6rk4a1f@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+83 -80
+1 -1
tools/perf/builtin-diff.c
··· 654 654 for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) { 655 655 struct diff_hpp_fmt *fmt = &d->fmt[col]; 656 656 657 - free(fmt->header); 657 + zfree(&fmt->header); 658 658 } 659 659 } 660 660
+1 -1
tools/perf/builtin-sched.c
··· 469 469 char comm2[22]; 470 470 int fd; 471 471 472 - free(parms); 472 + zfree(&parms); 473 473 474 474 sprintf(comm2, ":%s", this_task->comm); 475 475 prctl(PR_SET_NAME, comm2);
+3 -3
tools/perf/builtin-script.c
··· 1102 1102 1103 1103 static void script_desc__delete(struct script_desc *s) 1104 1104 { 1105 - free(s->name); 1106 - free(s->half_liner); 1107 - free(s->args); 1105 + zfree(&s->name); 1106 + zfree(&s->half_liner); 1107 + zfree(&s->args); 1108 1108 free(s); 1109 1109 } 1110 1110
+1 -1
tools/perf/ui/browsers/hists.c
··· 1327 1327 1328 1328 abs_path[nr_options] = strdup(path); 1329 1329 if (!abs_path[nr_options]) { 1330 - free(options[nr_options]); 1330 + zfree(&options[nr_options]); 1331 1331 ui__warning("Can't search all data files due to memory shortage.\n"); 1332 1332 fclose(file); 1333 1333 break;
+1 -1
tools/perf/ui/stdio/hist.c
··· 510 510 511 511 free(line); 512 512 out: 513 - free(rem_sq_bracket); 513 + zfree(&rem_sq_bracket); 514 514 515 515 return ret; 516 516 }
+10 -10
tools/perf/util/annotate.c
··· 26 26 27 27 static void ins__delete(struct ins_operands *ops) 28 28 { 29 - free(ops->source.raw); 30 - free(ops->source.name); 31 - free(ops->target.raw); 32 - free(ops->target.name); 29 + zfree(&ops->source.raw); 30 + zfree(&ops->source.name); 31 + zfree(&ops->target.raw); 32 + zfree(&ops->target.name); 33 33 } 34 34 35 35 static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, ··· 204 204 205 205 static void lock__delete(struct ins_operands *ops) 206 206 { 207 - free(ops->locked.ops); 208 - free(ops->target.raw); 209 - free(ops->target.name); 207 + zfree(&ops->locked.ops); 208 + zfree(&ops->target.raw); 209 + zfree(&ops->target.name); 210 210 } 211 211 212 212 static struct ins_ops lock_ops = { ··· 583 583 return dl; 584 584 585 585 out_free_line: 586 - free(dl->line); 586 + zfree(&dl->line); 587 587 out_delete: 588 588 free(dl); 589 589 return NULL; ··· 591 591 592 592 void disasm_line__free(struct disasm_line *dl) 593 593 { 594 - free(dl->line); 595 - free(dl->name); 594 + zfree(&dl->line); 595 + zfree(&dl->name); 596 596 if (dl->ins && dl->ins->ops->free) 597 597 dl->ins->ops->free(&dl->ops); 598 598 else
+1 -1
tools/perf/util/cgroup.c
··· 133 133 /* XXX: not reentrant */ 134 134 if (--cgrp->refcnt == 0) { 135 135 close(cgrp->fd); 136 - free(cgrp->name); 136 + zfree(&cgrp->name); 137 137 free(cgrp); 138 138 } 139 139 }
+1 -1
tools/perf/util/comm.c
··· 21 21 { 22 22 if (!--cs->ref) { 23 23 rb_erase(&cs->rb_node, &comm_str_root); 24 - free(cs->str); 24 + zfree(&cs->str); 25 25 free(cs); 26 26 } 27 27 }
+4 -4
tools/perf/util/evsel.c
··· 208 208 return evsel; 209 209 210 210 out_free: 211 - free(evsel->name); 211 + zfree(&evsel->name); 212 212 free(evsel); 213 213 return NULL; 214 214 } ··· 766 766 767 767 void perf_evsel__free_counts(struct perf_evsel *evsel) 768 768 { 769 - free(evsel->counts); 769 + zfree(&evsel->counts); 770 770 } 771 771 772 772 void perf_evsel__exit(struct perf_evsel *evsel) ··· 780 780 { 781 781 perf_evsel__exit(evsel); 782 782 close_cgroup(evsel->cgrp); 783 - free(evsel->group_name); 783 + zfree(&evsel->group_name); 784 784 if (evsel->tp_format) 785 785 pevent_free_format(evsel->tp_format); 786 - free(evsel->name); 786 + zfree(&evsel->name); 787 787 free(evsel); 788 788 } 789 789
+5 -5
tools/perf/util/header.c
··· 800 800 return; 801 801 802 802 for (i = 0 ; i < tp->core_sib; i++) 803 - free(tp->core_siblings[i]); 803 + zfree(&tp->core_siblings[i]); 804 804 805 805 for (i = 0 ; i < tp->thread_sib; i++) 806 - free(tp->thread_siblings[i]); 806 + zfree(&tp->thread_siblings[i]); 807 807 808 808 free(tp); 809 809 } ··· 1232 1232 return; 1233 1233 1234 1234 for (evsel = events; evsel->attr.size; evsel++) { 1235 - free(evsel->name); 1236 - free(evsel->id); 1235 + zfree(&evsel->name); 1236 + zfree(&evsel->id); 1237 1237 } 1238 1238 1239 1239 free(events); ··· 2105 2105 ret = 0; 2106 2106 out_free: 2107 2107 for (i = 0; i < nr_groups; i++) 2108 - free(desc[i].name); 2108 + zfree(&desc[i].name); 2109 2109 free(desc); 2110 2110 2111 2111 return ret;
+2 -2
tools/perf/util/help.c
··· 22 22 unsigned int i; 23 23 24 24 for (i = 0; i < cmds->cnt; ++i) 25 - free(cmds->names[i]); 26 - free(cmds->names); 25 + zfree(&cmds->names[i]); 26 + zfree(&cmds->names); 27 27 cmds->cnt = 0; 28 28 cmds->alloc = 0; 29 29 }
+3 -3
tools/perf/util/hist.c
··· 372 372 * This mem info was allocated from machine__resolve_mem 373 373 * and will not be used anymore. 374 374 */ 375 - free(entry->mem_info); 375 + zfree(&entry->mem_info); 376 376 377 377 /* If the map of an existing hist_entry has 378 378 * become out-of-date due to an exec() or ··· 475 475 476 476 void hist_entry__free(struct hist_entry *he) 477 477 { 478 - free(he->branch_info); 479 - free(he->mem_info); 478 + zfree(&he->branch_info); 479 + zfree(&he->mem_info); 480 480 free_srcline(he->srcline); 481 481 free(he); 482 482 }
+4 -4
tools/perf/util/parse-events.c
··· 204 204 } 205 205 path->name = malloc(MAX_EVENT_LENGTH); 206 206 if (!path->name) { 207 - free(path->system); 207 + zfree(&path->system); 208 208 free(path); 209 209 return NULL; 210 210 } ··· 236 236 path->name = strdup(str+1); 237 237 238 238 if (path->system == NULL || path->name == NULL) { 239 - free(path->system); 240 - free(path->name); 239 + zfree(&path->system); 240 + zfree(&path->name); 241 241 free(path); 242 242 path = NULL; 243 243 } ··· 917 917 ret = parse_events__scanner(str, &data, PE_START_TERMS); 918 918 if (!ret) { 919 919 list_splice(data.terms, terms); 920 - free(data.terms); 920 + zfree(&data.terms); 921 921 return 0; 922 922 } 923 923
+1 -1
tools/perf/util/pmu.c
··· 755 755 continue; 756 756 } 757 757 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 758 - free(aliases[j]); 758 + zfree(&aliases[j]); 759 759 printed++; 760 760 } 761 761 if (printed)
+4 -4
tools/perf/util/probe-event.c
··· 356 356 offset = tevs[i].point.address - stext; 357 357 offset += tevs[i].point.offset; 358 358 tevs[i].point.offset = 0; 359 - free(tevs[i].point.symbol); 359 + zfree(&tevs[i].point.symbol); 360 360 ret = e_snprintf(buf, 32, "0x%lx", offset); 361 361 if (ret < 0) 362 362 break; ··· 683 683 */ 684 684 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 685 685 vl->point.offset); 686 - free(vl->point.symbol); 686 + zfree(&vl->point.symbol); 687 687 nvars = 0; 688 688 if (vl->vars) { 689 689 strlist__for_each(node, vl->vars) { ··· 1592 1592 field = pev->args[i].field; 1593 1593 while (field) { 1594 1594 next = field->next; 1595 - free(field->name); 1595 + zfree(&field->name); 1596 1596 free(field); 1597 1597 field = next; 1598 1598 } ··· 2153 2153 for (i = 0; i < npevs; i++) { 2154 2154 for (j = 0; j < pkgs[i].ntevs; j++) 2155 2155 clear_probe_trace_event(&pkgs[i].tevs[j]); 2156 - free(pkgs[i].tevs); 2156 + zfree(&pkgs[i].tevs); 2157 2157 } 2158 2158 free(pkgs); 2159 2159
+1 -1
tools/perf/util/probe-finder.c
··· 1409 1409 if (ret < 0) { 1410 1410 /* Free vlist for error */ 1411 1411 while (af.nvls--) { 1412 - free(af.vls[af.nvls].point.symbol); 1412 + zfree(&af.vls[af.nvls].point.symbol); 1413 1413 strlist__delete(af.vls[af.nvls].vars); 1414 1414 } 1415 1415 zfree(vls);
+11 -11
tools/perf/util/session.c
··· 132 132 133 133 static void perf_session_env__delete(struct perf_session_env *env) 134 134 { 135 - free(env->hostname); 136 - free(env->os_release); 137 - free(env->version); 138 - free(env->arch); 139 - free(env->cpu_desc); 140 - free(env->cpuid); 135 + zfree(&env->hostname); 136 + zfree(&env->os_release); 137 + zfree(&env->version); 138 + zfree(&env->arch); 139 + zfree(&env->cpu_desc); 140 + zfree(&env->cpuid); 141 141 142 - free(env->cmdline); 143 - free(env->sibling_cores); 144 - free(env->sibling_threads); 145 - free(env->numa_nodes); 146 - free(env->pmu_mappings); 142 + zfree(&env->cmdline); 143 + zfree(&env->sibling_cores); 144 + zfree(&env->sibling_threads); 145 + zfree(&env->numa_nodes); 146 + zfree(&env->pmu_mappings); 147 147 } 148 148 149 149 void perf_session__delete(struct perf_session *session)
+3 -3
tools/perf/util/srcline.c
··· 129 129 130 130 out: 131 131 if (a2l) { 132 - free((void *)a2l->input); 132 + zfree((void **)&a2l->input); 133 133 free(a2l); 134 134 } 135 135 bfd_close(abfd); ··· 140 140 { 141 141 if (a2l->abfd) 142 142 bfd_close(a2l->abfd); 143 - free((void *)a2l->input); 144 - free(a2l->syms); 143 + zfree((void **)&a2l->input); 144 + zfree(&a2l->syms); 145 145 free(a2l); 146 146 } 147 147
+1 -1
tools/perf/util/strbuf.c
··· 28 28 void strbuf_release(struct strbuf *sb) 29 29 { 30 30 if (sb->alloc) { 31 - free(sb->buf); 31 + zfree(&sb->buf); 32 32 strbuf_init(sb, 0); 33 33 } 34 34 }
+1 -1
tools/perf/util/strfilter.c
··· 14 14 { 15 15 if (node) { 16 16 if (node->p && !is_operator(*node->p)) 17 - free((char *)node->p); 17 + zfree((char **)&node->p); 18 18 strfilter_node__delete(node->l); 19 19 strfilter_node__delete(node->r); 20 20 free(node);
+1 -1
tools/perf/util/string.c
··· 128 128 { 129 129 char **p; 130 130 for (p = argv; *p; p++) 131 - free(*p); 131 + zfree(p); 132 132 133 133 free(argv); 134 134 }
+2 -1
tools/perf/util/strlist.c
··· 5 5 */ 6 6 7 7 #include "strlist.h" 8 + #include "util.h" 8 9 #include <errno.h> 9 10 #include <stdio.h> 10 11 #include <stdlib.h> ··· 39 38 static void str_node__delete(struct str_node *snode, bool dupstr) 40 39 { 41 40 if (dupstr) 42 - free((void *)snode->s); 41 + zfree((void **)&snode->s); 43 42 free(snode); 44 43 } 45 44
+3 -2
tools/perf/util/svghelper.c
··· 21 21 22 22 #include "perf.h" 23 23 #include "svghelper.h" 24 + #include "util.h" 24 25 #include "cpumap.h" 25 26 26 27 static u64 first_time, last_time; ··· 709 708 return 0; 710 709 711 710 exit: 712 - free(t.sib_core); 713 - free(t.sib_thr); 711 + zfree(&t.sib_core); 712 + zfree(&t.sib_thr); 714 713 715 714 return -1; 716 715 }
+1 -1
tools/perf/util/symbol-elf.c
··· 554 554 555 555 void symsrc__destroy(struct symsrc *ss) 556 556 { 557 - free(ss->name); 557 + zfree(&ss->name); 558 558 elf_end(ss->elf); 559 559 close(ss->fd); 560 560 }
+2 -1
tools/perf/util/symbol-minimal.c
··· 1 1 #include "symbol.h" 2 + #include "util.h" 2 3 3 4 #include <stdio.h> 4 5 #include <fcntl.h> ··· 276 275 277 276 void symsrc__destroy(struct symsrc *ss) 278 277 { 279 - free(ss->name); 278 + zfree(&ss->name); 280 279 close(ss->fd); 281 280 } 282 281
+1 -1
tools/perf/util/symbol.c
··· 796 796 mi = rb_entry(next, struct module_info, rb_node); 797 797 next = rb_next(&mi->rb_node); 798 798 rb_erase(&mi->rb_node, modules); 799 - free(mi->name); 799 + zfree(&mi->name); 800 800 free(mi); 801 801 } 802 802 }
+5 -5
tools/perf/util/thread_map.c
··· 41 41 } 42 42 43 43 for (i=0; i<items; i++) 44 - free(namelist[i]); 44 + zfree(&namelist[i]); 45 45 free(namelist); 46 46 47 47 return threads; ··· 118 118 threads->map[threads->nr + i] = atoi(namelist[i]->d_name); 119 119 120 120 for (i = 0; i < items; i++) 121 - free(namelist[i]); 121 + zfree(&namelist[i]); 122 122 free(namelist); 123 123 124 124 threads->nr += items; ··· 135 135 136 136 out_free_namelist: 137 137 for (i = 0; i < items; i++) 138 - free(namelist[i]); 138 + zfree(&namelist[i]); 139 139 free(namelist); 140 140 141 141 out_free_closedir: ··· 194 194 195 195 for (i = 0; i < items; i++) { 196 196 threads->map[j++] = atoi(namelist[i]->d_name); 197 - free(namelist[i]); 197 + zfree(&namelist[i]); 198 198 } 199 199 threads->nr = total_tasks; 200 200 free(namelist); ··· 206 206 207 207 out_free_namelist: 208 208 for (i = 0; i < items; i++) 209 - free(namelist[i]); 209 + zfree(&namelist[i]); 210 210 free(namelist); 211 211 212 212 out_free_threads:
+2 -2
tools/perf/util/trace-event-info.c
··· 397 397 struct tracepoint_path *t = tps; 398 398 399 399 tps = tps->next; 400 - free(t->name); 401 - free(t->system); 400 + zfree(&t->name); 401 + zfree(&t->system); 402 402 free(t); 403 403 } 404 404 }
+7 -7
tools/perf/util/values.c
··· 31 31 return; 32 32 33 33 for (i = 0; i < values->threads; i++) 34 - free(values->value[i]); 35 - free(values->value); 36 - free(values->pid); 37 - free(values->tid); 38 - free(values->counterrawid); 34 + zfree(&values->value[i]); 35 + zfree(&values->value); 36 + zfree(&values->pid); 37 + zfree(&values->tid); 38 + zfree(&values->counterrawid); 39 39 for (i = 0; i < values->counters; i++) 40 - free(values->countername[i]); 41 - free(values->countername); 40 + zfree(&values->countername[i]); 41 + zfree(&values->countername); 42 42 } 43 43 44 44 static void perf_read_values__enlarge_threads(struct perf_read_values *values)