Skip to contentSkip to conversation

perf tools: Fix crash in perf_hpp__reset_output_field

PATCH In review Jiri Olsa 3 participants 4 messages Jun 1, 2017 perf events

lore
Share & tools
lore

Jiri Olsa

author reviewer
#0 lore raw

PATCH 1/2 perf tools: Fix crash in perf_hpp__reset_output_field

Du Changbin reported crash [1] when calling perf_hpp__reset_output_field after unregistering field via perf_hpp__column_unregister.

This ends up in calling following list_del* sequence on the same format:

  perf_hpp__column_unregister:
    list_del(&format->list);
  perf_hpp__reset_output_field:
    list_del_init(&fmt->list);

where the later list_del_init might touch already
freed formats.

Fixing this by replacing list_del with list_del_init in perf_hpp__column_unregister.

[1] http://marc.info/?l=linux-kernel&m=149059595826019&w=2

---
 tools/perf/ui/hist.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/ui/hist.c +1 -1
index 59addd52d9cd..feb2174ddd1f 100644
@@ -530,7 +530,7 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
 
 void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
 {
-	list_del(&format->list);
+	list_del_init(&format->list);
 }
 
 void perf_hpp__cancel_cumulate(void)
Signature · 1 line
2.9.4
author reviewer
#1 lore raw

PATCH 2/2 perf tools: Remove extra list_del_init calls in list reset

We only needs to remove the format from the currently iterated list. The other removals/inits are superfluous because we free the format in any case.

---
 tools/perf/ui/hist.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/ui/hist.c +4 -4
index feb2174ddd1f..a0fee2ac8599 100644
@@ -614,15 +614,15 @@ void perf_hpp__reset_output_field(struct perf_hpp_list *list)
 
 	/* reset output fields */
 	perf_hpp_list__for_each_format_safe(list, fmt, tmp) {
-		list_del_init(&fmt->list);
-		list_del_init(&fmt->sort_list);
+		list_del(&fmt->list);
+		/* Remove the fmt from next loop processing. */
+		list_del(&fmt->sort_list);
 		fmt_free(fmt);
 	}
 
 	/* reset sort keys */
 	perf_hpp_list__for_each_sort_list_safe(list, fmt, tmp) {
-		list_del_init(&fmt->list);
-		list_del_init(&fmt->sort_list);
+		list_del(&fmt->sort_list);
 		fmt_free(fmt);
 	}
 }
Signature · 1 line
2.9.4
#2 lore raw

Re: [PATCH 2/2] perf tools: Remove extra list_del_init calls in list reset

Em Thu, Jun 01, 2017 at 01:17:44PM +0200, Jiri Olsa escreveu:

Quoted 15 lines

We only needs to remove the format from the currently iterated list. The other removals/inits are superfluous because we free the format in any case.

---
 tools/perf/ui/hist.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/ui/hist.c +0 -0
index feb2174ddd1f..a0fee2ac8599 100644

tools/perf/ui/hist.c void perf_hpp__reset_output_field(struct perf_hpp_list *list) · line 619

Quoted 8 lines
tools/perf/ui/hist.c +3 -2
@@ -614,15 +614,15 @@ void perf_hpp__reset_output_field(struct perf_hpp_list *list)
 
 	/* reset output fields */
 	perf_hpp_list__for_each_format_safe(list, fmt, tmp) {
-		list_del_init(&fmt->list);
-		list_del_init(&fmt->sort_list);
+		list_del(&fmt->list);
+		/* Remove the fmt from next loop processing. */
+		list_del(&fmt->sort_list);

Why not just add the comment and leave it as list_del_init(), then, in fmt_free() -> fmt->free() -> hse_free() (for instance), have:

	BUG_ON(!list_empty(&fmt->list));
	BUG_ON(!list_empty(&fmt->sort_list));

The patch would be smaller and overall the code would be more robust?

tools/perf/ui/hist.c void perf_hpp__reset_output_field(struct perf_hpp_list *list) · line 625

Quoted 8 lines
tools/perf/ui/hist.c +1 -2
 		fmt_free(fmt);
 	}
 
 	/* reset sort keys */
 	perf_hpp_list__for_each_sort_list_safe(list, fmt, tmp) {
-		list_del_init(&fmt->list);
-		list_del_init(&fmt->sort_list);
+		list_del(&fmt->sort_list);

Ditto, just ditch what you said you would do in the cset comment, i.e. ditch the extra "list_del_init(&fmt->list);" call, no?

- Arnaldo

Quoted 5 lines
tools/perf/ui/hist.c +0 -0
 		fmt_free(fmt);
 	}
 }
Signature · 1 line
2.9.4
#3 lore raw

Re: [PATCH 2/2] perf tools: Remove extra list_del_init calls in list reset

Quoted 28 lines · Arnaldo Carvalho de Melo

Em Thu, Jun 01, 2017 at 01:17:44PM +0200, Jiri Olsa escreveu:

Quoted 15 lines

We only needs to remove the format from the currently iterated list. The other removals/inits are superfluous because we free the format in any case.

---
 tools/perf/ui/hist.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
tools/perf/ui/hist.c +0 -0
index feb2174ddd1f..a0fee2ac8599 100644

tools/perf/ui/hist.c void perf_hpp__reset_output_field(struct perf_hpp_list *list) · line 619

Quoted 8 lines
tools/perf/ui/hist.c +3 -2
@@ -614,15 +614,15 @@ void perf_hpp__reset_output_field(struct perf_hpp_list *list)
 
 	/* reset output fields */
 	perf_hpp_list__for_each_format_safe(list, fmt, tmp) {
-		list_del_init(&fmt->list);
-		list_del_init(&fmt->sort_list);
+		list_del(&fmt->list);
+		/* Remove the fmt from next loop processing. */
+		list_del(&fmt->sort_list);

Why not just add the comment and leave it as list_del_init(), then, in fmt_free() -> fmt->free() -> hse_free() (for instance), have:

Quoted 4 lines
	BUG_ON(!list_empty(&fmt->list));
	BUG_ON(!list_empty(&fmt->sort_list));

The patch would be smaller and overall the code would be more robust?

ok, that could catch something.. will change

thanks,
jirka