lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 20 Apr 2020 11:05:00 +0200
From:   Jiri Olsa <jolsa@...hat.com>
To:     Tommi Rantala <tommi.t.rantala@...ia.com>
Cc:     Arnaldo Carvalho de Melo <acme@...nel.org>,
        Ingo Molnar <mingo@...hat.com>,
        Peter Zijlstra <peterz@...radead.org>,
        Mark Rutland <mark.rutland@....com>,
        Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
        Namhyung Kim <namhyung@...nel.org>,
        Alexey Budankov <alexey.budankov@...ux.intel.com>,
        Adrian Hunter <adrian.hunter@...el.com>,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH 3/4] perf tools: Fix segfaults due to missing zstd
 decompressor initialization

On Fri, Apr 17, 2020 at 04:23:28PM +0300, Tommi Rantala wrote:
> Initialization of zstd decompressor state is done for "perf report" and
> "perf inject", but missing for other tools, causing segfaults e.g. with
> "perf script" and "perf annotate" when zstd compressed data is used:
> 
>   # ./perf record -z -a -- sleep 1
>   # gdb -q --args ./perf script
>   (gdb) run
>   Program received signal SIGSEGV, Segmentation fault.
>   0x00007ffff771d4cb in ZSTD_decompressStream () from /lib64/libzstd.so.1
>   (gdb) bt
>   #0  0x00007ffff771d4cb in ZSTD_decompressStream () from /lib64/libzstd.so.1
>   #1  0x00000000005c92a8 in zstd_decompress_stream (data=0xc3f8e0, src=0x7ffff6dd3038, src_size=255, dst=0x7ffff61ec028, dst_size=528384) at util/zstd.c:100
>   #2  0x00000000005262ba in perf_session__process_compressed_event (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:73
>   #3  0x000000000052a596 in perf_session__process_user_event (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:1581
>   #4  0x000000000052ab4b in perf_session__process_event (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:1713
>   #5  0x000000000052bed6 in process_simple (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:2209
>   #6  0x000000000052bcfe in reader__process_events (rd=0x7fffffffb400, session=0xc38cc0, prog=0x7fffffffb420) at util/session.c:2175
>   #7  0x000000000052bfc2 in __perf_session__process_events (session=0xc38cc0) at util/session.c:2232
>   #8  0x000000000052c0f3 in perf_session__process_events (session=0xc38cc0) at util/session.c:2265
>   #9  0x0000000000447266 in __cmd_script (script=0x7fffffffb5c0) at builtin-script.c:2608
>   #10 0x000000000044ba79 in cmd_script (argc=0, argv=0x7fffffffd330) at builtin-script.c:3988
>   #11 0x00000000004bf2b8 in run_builtin (p=0xa398f8 <commands+408>, argc=1, argv=0x7fffffffd330) at perf.c:312
>   #12 0x00000000004bf525 in handle_internal_command (argc=1, argv=0x7fffffffd330) at perf.c:364
>   #13 0x00000000004bf66c in run_argv (argcp=0x7fffffffd18c, argv=0x7fffffffd180) at perf.c:408
>   #14 0x00000000004bfa38 in main (argc=1, argv=0x7fffffffd330) at perf.c:538
> 
> Split zstd_init() into zstd_decomp_init() and zstd_comp_init(), so that
> we can do lazy initialization for the decompressor, and handle it all in
> perf_session to make it easily available to all the tools.

Alexey, could you please check on this one?

thanks,
jirka

> 
> Signed-off-by: Tommi Rantala <tommi.t.rantala@...ia.com>
> ---
>  tools/perf/builtin-inject.c |  3 ---
>  tools/perf/builtin-record.c |  2 +-
>  tools/perf/builtin-report.c |  3 ---
>  tools/perf/util/compress.h  | 10 ++++++++--
>  tools/perf/util/session.c   |  3 +++
>  tools/perf/util/zstd.c      | 14 +++++++++++++-
>  6 files changed, 25 insertions(+), 10 deletions(-)
> 
> diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> index 1ffb8393357a..8cc9dff9e66b 100644
> --- a/tools/perf/builtin-inject.c
> +++ b/tools/perf/builtin-inject.c
> @@ -803,9 +803,6 @@ int cmd_inject(int argc, const char **argv)
>  	if (IS_ERR(inject.session))
>  		return PTR_ERR(inject.session);
>  
> -	if (zstd_init(&(inject.session->zstd_data), 0) < 0)
> -		pr_warning("Decompression initialization failed.\n");
> -
>  	if (inject.build_ids) {
>  		/*
>  		 * to make sure the mmap records are ordered correctly
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 8ed00de1ca29..fa9c59fc4fe0 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -1461,7 +1461,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
>  	fd = perf_data__fd(data);
>  	rec->session = session;
>  
> -	if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) {
> +	if (zstd_comp_init(&session->zstd_data, rec->opts.comp_level) < 0) {
>  		pr_err("Compression initialization failed.\n");
>  		return -1;
>  	}
> diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
> index e06e14980264..b85fcdebdb5a 100644
> --- a/tools/perf/builtin-report.c
> +++ b/tools/perf/builtin-report.c
> @@ -1355,9 +1355,6 @@ int cmd_report(int argc, const char **argv)
>  	if (ret)
>  		return ret;
>  
> -	if (zstd_init(&(session->zstd_data), 0) < 0)
> -		pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
> -
>  	if (report.queue_size) {
>  		ordered_events__set_alloc_size(&session->ordered_events,
>  					       report.queue_size);
> diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
> index 0cd3369af2a4..aff9ce60dfb8 100644
> --- a/tools/perf/util/compress.h
> +++ b/tools/perf/util/compress.h
> @@ -26,7 +26,8 @@ struct zstd_data {
>  
>  #ifdef HAVE_ZSTD_SUPPORT
>  
> -int zstd_init(struct zstd_data *data, int level);
> +int zstd_comp_init(struct zstd_data *data, int level);
> +int zstd_decomp_init(struct zstd_data *data);
>  int zstd_fini(struct zstd_data *data);
>  
>  size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size,
> @@ -37,7 +38,12 @@ size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size
>  			      void *dst, size_t dst_size);
>  #else /* !HAVE_ZSTD_SUPPORT */
>  
> -static inline int zstd_init(struct zstd_data *data __maybe_unused, int level __maybe_unused)
> +static inline int zstd_comp_init(struct zstd_data *data __maybe_unused, int level __maybe_unused)
> +{
> +	return 0;
> +}
> +
> +static inline int zstd_decomp_init(struct zstd_data *data __maybe_unused)
>  {
>  	return 0;
>  }
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index 64e8b794b0bc..2bba731e7cbf 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -45,6 +45,9 @@ static int perf_session__process_compressed_event(struct perf_session *session,
>  	size_t mmap_len, decomp_len = session->header.env.comp_mmap_len;
>  	struct decomp *decomp, *decomp_last = session->decomp_last;
>  
> +	if (zstd_decomp_init(&session->zstd_data) < 0)
> +		return -1;
> +
>  	if (decomp_last) {
>  		decomp_last_rem = decomp_last->size - decomp_last->head;
>  		decomp_len += decomp_last_rem;
> diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c
> index d2202392ffdb..d789665e8c0c 100644
> --- a/tools/perf/util/zstd.c
> +++ b/tools/perf/util/zstd.c
> @@ -5,10 +5,13 @@
>  #include "util/compress.h"
>  #include "util/debug.h"
>  
> -int zstd_init(struct zstd_data *data, int level)
> +int zstd_decomp_init(struct zstd_data *data)
>  {
>  	size_t ret;
>  
> +	if (data->dstream)
> +		return 0;
> +
>  	data->dstream = ZSTD_createDStream();
>  	if (data->dstream == NULL) {
>  		pr_err("Couldn't create decompression stream.\n");
> @@ -18,9 +21,18 @@ int zstd_init(struct zstd_data *data, int level)
>  	ret = ZSTD_initDStream(data->dstream);
>  	if (ZSTD_isError(ret)) {
>  		pr_err("Failed to initialize decompression stream: %s\n", ZSTD_getErrorName(ret));
> +		ZSTD_freeDStream(data->dstream);
> +		data->dstream = NULL;
>  		return -1;
>  	}
>  
> +	return 0;
> +}
> +
> +int zstd_comp_init(struct zstd_data *data, int level)
> +{
> +	size_t ret;
> +
>  	if (!level)
>  		return 0;
>  
> -- 
> 2.25.2
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ