All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] perf session: fix decompression of PERF_RECORD_COMPRESSED records
@ 2019-11-18 14:21 Alexey Budankov
  2019-11-19 20:05 ` Jiri Olsa
  2019-11-23  8:15 ` [tip: perf/core] perf session: Fix " tip-bot2 for Alexey Budankov
  0 siblings, 2 replies; 4+ messages in thread
From: Alexey Budankov @ 2019-11-18 14:21 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Namhyung Kim, Alexander Shishkin, Peter Zijlstra,
	Ingo Molnar, Andi Kleen, linux-kernel


Avoid termination of trace loading in case the last record in
the decompressed buffer partly resides in the following
mmaped PERF_RECORD_COMPRESSED record. In this case NULL value
returned by fetch_mmaped_event() means to proceed to the next
mmaped record then decompress it and load compressed events.

The issue can be reproduced like this:

  $ perf record -z -- some_long_running_workload
  $ perf report --stdio -vv
  decomp (B): 44519 to 163000
  decomp (B): 48119 to 174800
  decomp (B): 65527 to 131072
  fetch_mmaped_event: head=0x1ffe0 event->header_size=0x28, mmap_size=0x20000: fuzzed perf.data?
  Error:
  failed to process sample
  ...

Testing:

  71: Zstd perf.data compression/decompression              : Ok

  $ tools/perf/perf report -vv --stdio
  decomp (B): 59593 to 262160
  decomp (B): 4438 to 16512
  decomp (B): 285 to 880
  Looking at the vmlinux_path (8 entries long)
  Using vmlinux for symbols
  decomp (B): 57474 to 261248
  prefetch_event: head=0x3fc78 event->header_size=0x28, mmap_size=0x3fc80: fuzzed or compressed perf.data?
  decomp (B): 25 to 32
  decomp (B): 52 to 120
  ...

Fixes: 57fc032ad643 ("perf session: Avoid infinite loop when seeing invalid header.size")
Link: https://marc.info/?l=linux-kernel&m=156580812427554&w=2
Co-developed-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>
---
Changes in v3:
- extended debug message with 'fuzzed or compressed perf.data?'
Changes in v2:
- avoided static declaration of prefetch_event();
- renamed 'ret' to 'error' for returning in case of split compressed 
  or overlapping records;
- passed only needs_swap quality into fetch_*_event() instead of 
  the whole session object;
---
 tools/perf/util/session.c | 44 ++++++++++++++++++++++++---------------
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f07b8ecb91bc..8454a650146b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1958,8 +1958,8 @@ static int __perf_session__process_pipe_events(struct perf_session *session)
 }
 
 static union perf_event *
-fetch_mmaped_event(struct perf_session *session,
-		   u64 head, size_t mmap_size, char *buf)
+prefetch_event(char *buf, u64 head, size_t mmap_size,
+	       bool needs_swap, union perf_event *error)
 {
 	union perf_event *event;
 
@@ -1971,20 +1971,32 @@ fetch_mmaped_event(struct perf_session *session,
 		return NULL;
 
 	event = (union perf_event *)(buf + head);
+	if (needs_swap)
+		perf_event_header__bswap(&event->header);
 
-	if (session->header.needs_swap)
+	if (head + event->header.size <= mmap_size)
+		return event;
+
+	/* We're not fetching the event so swap back again */
+	if (needs_swap)
 		perf_event_header__bswap(&event->header);
 
-	if (head + event->header.size > mmap_size) {
-		/* We're not fetching the event so swap back again */
-		if (session->header.needs_swap)
-			perf_event_header__bswap(&event->header);
-		pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx: fuzzed perf.data?\n",
-			 __func__, head, event->header.size, mmap_size);
-		return ERR_PTR(-EINVAL);
-	}
+	pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx:"
+		 " fuzzed or compressed perf.data?\n",__func__, head, event->header.size, mmap_size);
 
-	return event;
+	return error;
+}
+
+static union perf_event *
+fetch_mmaped_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)
+{
+	return prefetch_event(buf, head, mmap_size, needs_swap, ERR_PTR(-EINVAL));
+}
+
+static union perf_event *
+fetch_decomp_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)
+{
+	return prefetch_event(buf, head, mmap_size, needs_swap, NULL);
 }
 
 static int __perf_session__process_decomp_events(struct perf_session *session)
@@ -1997,10 +2009,8 @@ static int __perf_session__process_decomp_events(struct perf_session *session)
 		return 0;
 
 	while (decomp->head < decomp->size && !session_done()) {
-		union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data);
-
-		if (IS_ERR(event))
-			return PTR_ERR(event);
+		union perf_event *event = fetch_decomp_event(decomp->head, decomp->size, decomp->data,
+							     session->header.needs_swap);
 
 		if (!event)
 			break;
@@ -2100,7 +2110,7 @@ reader__process_events(struct reader *rd, struct perf_session *session,
 	}
 
 more:
-	event = fetch_mmaped_event(session, head, mmap_size, buf);
+	event = fetch_mmaped_event(head, mmap_size, buf, session->header.needs_swap);
 	if (IS_ERR(event))
 		return PTR_ERR(event);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3] perf session: fix decompression of PERF_RECORD_COMPRESSED records
  2019-11-18 14:21 [PATCH v3] perf session: fix decompression of PERF_RECORD_COMPRESSED records Alexey Budankov
@ 2019-11-19 20:05 ` Jiri Olsa
  2019-11-19 22:33   ` Arnaldo Carvalho de Melo
  2019-11-23  8:15 ` [tip: perf/core] perf session: Fix " tip-bot2 for Alexey Budankov
  1 sibling, 1 reply; 4+ messages in thread
From: Jiri Olsa @ 2019-11-19 20:05 UTC (permalink / raw)
  To: Alexey Budankov
  Cc: Arnaldo Carvalho de Melo, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Ingo Molnar, Andi Kleen, linux-kernel

On Mon, Nov 18, 2019 at 05:21:03PM +0300, Alexey Budankov wrote:
> 
> Avoid termination of trace loading in case the last record in
> the decompressed buffer partly resides in the following
> mmaped PERF_RECORD_COMPRESSED record. In this case NULL value
> returned by fetch_mmaped_event() means to proceed to the next
> mmaped record then decompress it and load compressed events.
> 
> The issue can be reproduced like this:
> 
>   $ perf record -z -- some_long_running_workload
>   $ perf report --stdio -vv
>   decomp (B): 44519 to 163000
>   decomp (B): 48119 to 174800
>   decomp (B): 65527 to 131072
>   fetch_mmaped_event: head=0x1ffe0 event->header_size=0x28, mmap_size=0x20000: fuzzed perf.data?
>   Error:
>   failed to process sample
>   ...
> 
> Testing:
> 
>   71: Zstd perf.data compression/decompression              : Ok
> 
>   $ tools/perf/perf report -vv --stdio
>   decomp (B): 59593 to 262160
>   decomp (B): 4438 to 16512
>   decomp (B): 285 to 880
>   Looking at the vmlinux_path (8 entries long)
>   Using vmlinux for symbols
>   decomp (B): 57474 to 261248
>   prefetch_event: head=0x3fc78 event->header_size=0x28, mmap_size=0x3fc80: fuzzed or compressed perf.data?
>   decomp (B): 25 to 32
>   decomp (B): 52 to 120
>   ...
> 
> Fixes: 57fc032ad643 ("perf session: Avoid infinite loop when seeing invalid header.size")
> Link: https://marc.info/?l=linux-kernel&m=156580812427554&w=2
> Co-developed-by: Jiri Olsa <jolsa@kernel.org>
> Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v3] perf session: fix decompression of PERF_RECORD_COMPRESSED records
  2019-11-19 20:05 ` Jiri Olsa
@ 2019-11-19 22:33   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 4+ messages in thread
From: Arnaldo Carvalho de Melo @ 2019-11-19 22:33 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexey Budankov, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra, Ingo Molnar, Andi Kleen, linux-kernel

Em Tue, Nov 19, 2019 at 09:05:10PM +0100, Jiri Olsa escreveu:
> On Mon, Nov 18, 2019 at 05:21:03PM +0300, Alexey Budankov wrote:
> > 
> > Avoid termination of trace loading in case the last record in
> > the decompressed buffer partly resides in the following
> > mmaped PERF_RECORD_COMPRESSED record. In this case NULL value
> > returned by fetch_mmaped_event() means to proceed to the next
> > mmaped record then decompress it and load compressed events.
> > 
> > The issue can be reproduced like this:
> > 
> >   $ perf record -z -- some_long_running_workload
> >   $ perf report --stdio -vv
> >   decomp (B): 44519 to 163000
> >   decomp (B): 48119 to 174800
> >   decomp (B): 65527 to 131072
> >   fetch_mmaped_event: head=0x1ffe0 event->header_size=0x28, mmap_size=0x20000: fuzzed perf.data?
> >   Error:
> >   failed to process sample
> >   ...
> > 
> > Testing:
> > 
> >   71: Zstd perf.data compression/decompression              : Ok
> > 
> >   $ tools/perf/perf report -vv --stdio
> >   decomp (B): 59593 to 262160
> >   decomp (B): 4438 to 16512
> >   decomp (B): 285 to 880
> >   Looking at the vmlinux_path (8 entries long)
> >   Using vmlinux for symbols
> >   decomp (B): 57474 to 261248
> >   prefetch_event: head=0x3fc78 event->header_size=0x28, mmap_size=0x3fc80: fuzzed or compressed perf.data?
> >   decomp (B): 25 to 32
> >   decomp (B): 52 to 120
> >   ...
> > 
> > Fixes: 57fc032ad643 ("perf session: Avoid infinite loop when seeing invalid header.size")
> > Link: https://marc.info/?l=linux-kernel&m=156580812427554&w=2
> > Co-developed-by: Jiri Olsa <jolsa@kernel.org>
> > Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>
> 
> Acked-by: Jiri Olsa <jolsa@kernel.org>

Thanks, applied.

- Arnaldo
 
> thanks,
> jirka

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [tip: perf/core] perf session: Fix decompression of PERF_RECORD_COMPRESSED records
  2019-11-18 14:21 [PATCH v3] perf session: fix decompression of PERF_RECORD_COMPRESSED records Alexey Budankov
  2019-11-19 20:05 ` Jiri Olsa
@ 2019-11-23  8:15 ` tip-bot2 for Alexey Budankov
  1 sibling, 0 replies; 4+ messages in thread
From: tip-bot2 for Alexey Budankov @ 2019-11-23  8:15 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Jiri Olsa, Alexey Budankov, Alexander Shishkin, Andi Kleen,
	Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo, x86,
	LKML

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     bb1835a3b86c73aa534ef6430ad40223728dfbc0
Gitweb:        https://git.kernel.org/tip/bb1835a3b86c73aa534ef6430ad40223728dfbc0
Author:        Alexey Budankov <alexey.budankov@linux.intel.com>
AuthorDate:    Mon, 18 Nov 2019 17:21:03 +03:00
Committer:     Arnaldo Carvalho de Melo <acme@redhat.com>
CommitterDate: Tue, 19 Nov 2019 19:31:55 -03:00

perf session: Fix decompression of PERF_RECORD_COMPRESSED records

Avoid termination of trace loading in case the last record in the
decompressed buffer partly resides in the following mmaped
PERF_RECORD_COMPRESSED record.

In this case NULL value returned by fetch_mmaped_event() means to
proceed to the next mmaped record then decompress it and load compressed
events.

The issue can be reproduced like this:

  $ perf record -z -- some_long_running_workload
  $ perf report --stdio -vv
  decomp (B): 44519 to 163000
  decomp (B): 48119 to 174800
  decomp (B): 65527 to 131072
  fetch_mmaped_event: head=0x1ffe0 event->header_size=0x28, mmap_size=0x20000: fuzzed perf.data?
  Error:
  failed to process sample
  ...

Testing:

  71: Zstd perf.data compression/decompression              : Ok

  $ tools/perf/perf report -vv --stdio
  decomp (B): 59593 to 262160
  decomp (B): 4438 to 16512
  decomp (B): 285 to 880
  Looking at the vmlinux_path (8 entries long)
  Using vmlinux for symbols
  decomp (B): 57474 to 261248
  prefetch_event: head=0x3fc78 event->header_size=0x28, mmap_size=0x3fc80: fuzzed or compressed perf.data?
  decomp (B): 25 to 32
  decomp (B): 52 to 120
  ...

Fixes: 57fc032ad643 ("perf session: Avoid infinite loop when seeing invalid header.size")
Link: https://marc.info/?l=linux-kernel&m=156580812427554&w=2
Co-developed-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/cf782c34-f3f8-2f9f-d6ab-145cee0d5322@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/session.c | 44 +++++++++++++++++++++++---------------
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f07b8ec..8454a65 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1958,8 +1958,8 @@ out_err:
 }
 
 static union perf_event *
-fetch_mmaped_event(struct perf_session *session,
-		   u64 head, size_t mmap_size, char *buf)
+prefetch_event(char *buf, u64 head, size_t mmap_size,
+	       bool needs_swap, union perf_event *error)
 {
 	union perf_event *event;
 
@@ -1971,20 +1971,32 @@ fetch_mmaped_event(struct perf_session *session,
 		return NULL;
 
 	event = (union perf_event *)(buf + head);
+	if (needs_swap)
+		perf_event_header__bswap(&event->header);
 
-	if (session->header.needs_swap)
+	if (head + event->header.size <= mmap_size)
+		return event;
+
+	/* We're not fetching the event so swap back again */
+	if (needs_swap)
 		perf_event_header__bswap(&event->header);
 
-	if (head + event->header.size > mmap_size) {
-		/* We're not fetching the event so swap back again */
-		if (session->header.needs_swap)
-			perf_event_header__bswap(&event->header);
-		pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx: fuzzed perf.data?\n",
-			 __func__, head, event->header.size, mmap_size);
-		return ERR_PTR(-EINVAL);
-	}
+	pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx:"
+		 " fuzzed or compressed perf.data?\n",__func__, head, event->header.size, mmap_size);
 
-	return event;
+	return error;
+}
+
+static union perf_event *
+fetch_mmaped_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)
+{
+	return prefetch_event(buf, head, mmap_size, needs_swap, ERR_PTR(-EINVAL));
+}
+
+static union perf_event *
+fetch_decomp_event(u64 head, size_t mmap_size, char *buf, bool needs_swap)
+{
+	return prefetch_event(buf, head, mmap_size, needs_swap, NULL);
 }
 
 static int __perf_session__process_decomp_events(struct perf_session *session)
@@ -1997,10 +2009,8 @@ static int __perf_session__process_decomp_events(struct perf_session *session)
 		return 0;
 
 	while (decomp->head < decomp->size && !session_done()) {
-		union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data);
-
-		if (IS_ERR(event))
-			return PTR_ERR(event);
+		union perf_event *event = fetch_decomp_event(decomp->head, decomp->size, decomp->data,
+							     session->header.needs_swap);
 
 		if (!event)
 			break;
@@ -2100,7 +2110,7 @@ remap:
 	}
 
 more:
-	event = fetch_mmaped_event(session, head, mmap_size, buf);
+	event = fetch_mmaped_event(head, mmap_size, buf, session->header.needs_swap);
 	if (IS_ERR(event))
 		return PTR_ERR(event);
 

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-11-23  8:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-18 14:21 [PATCH v3] perf session: fix decompression of PERF_RECORD_COMPRESSED records Alexey Budankov
2019-11-19 20:05 ` Jiri Olsa
2019-11-19 22:33   ` Arnaldo Carvalho de Melo
2019-11-23  8:15 ` [tip: perf/core] perf session: Fix " tip-bot2 for Alexey Budankov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.