Linux Perf Users
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Arnaldo Carvalho de Melo" <acme@kernel.org>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks
Date: Thu, 06 Aug 2026 12:52:02 +0000	[thread overview]
Message-ID: <20260806125203.3D5E01F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260806123604.271277-3-acme@kernel.org>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

Pre-existing issues:
- [Critical] The `csize` value from the untrusted JIT dump file is not validated against `total_size`, allowing an integer underflow that leads to a massive out-of-bounds heap read and information leak.
- [Critical] Output `.so` files are opened without `O_EXCL` and `O_NOFOLLOW` in a potentially attacker-controlled directory, allowing a symlink attack to overwrite arbitrary files.
- [High] Code load events fail to consume and free `unwinding_data` and `debug_data` if their respective auxiliary sizes or counts are zero, leading to state contamination.
- [High] Calling `funlockfile()` without a preceding `flockfile()` on the `malloc()` error path causes undefined behavior.
- [High] Missing bounds check on the JIT record `total_size` before accessing the `sym` string pointer causes an out-of-bounds string read.
--

--- Patch [2]: [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks ---
commit e7687575b20ca5df1e7780e1c7b436a5bc7d2f8c
Author: Arnaldo Carvalho de Melo <acme@redhat.com>

perf jitdump: Fix debug_data and unwinding_data leaks
    
This commit fixes memory leaks in jit_repipe_debug_info() and jit_close().
It uses zfree() to correctly free existing allocations before reassignment
and cleans up at the end of the session.

> diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
> --- a/tools/perf/util/jitdump.c
> +++ b/tools/perf/util/jitdump.c
> @@ -61,12 +61,12 @@ static int
>  jit_emit_elf(struct jit_buf_desc *jd,
>  	     char *filename,
[ ... ]
>  	nsinfo__mountns_enter(jd->nsi, &nsc);
>  	fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);

[Severity: Critical]
This isn't a bug introduced by this patch, but opening output files without
O_EXCL and O_NOFOLLOW in a potentially attacker-controlled directory might
allow a symlink attack to overwrite arbitrary files.

Could this be updated to use safer open flags?

[ ... ]

> @@ -117,6 +117,8 @@ jit_close(struct jit_buf_desc *jd)
>  	funlockfile(jd->in);
>  	fclose(jd->in);
>  	jd->in = NULL;
> +	zfree(&jd->debug_data);
> +	zfree(&jd->unwinding_data);
>  }

[ ... ]

> @@ -154,9 +154,9 @@ static int
>  jit_open(struct jit_buf_desc *jd, const char *name)
>  {
[ ... ]
>  	bsz = hmax(sizeof(header), sizeof(*prefix));
> 
>  	buf = malloc(bsz);
>  	if (!buf)
>  		goto error;
> 
>  	/*
>  	 * protect from writer modifying the file while we are reading it
>  	 */
>  	flockfile(jd->in);
[ ... ]
> @@ -217,9 +217,9 @@ static int
>  	return 0;
>  error:
>  	free(buf);
>  	funlockfile(jd->in);

[Severity: High]
This isn't a bug introduced by this patch, but if the initial malloc(bsz)
fails, we jump to error and call funlockfile(jd->in) without a preceding
flockfile().

Does calling funlockfile() on an unlocked FILE stream cause undefined
behavior or corruption of internal libc mutexes here?

>  	fclose(jd->in);
>  	return retval;
>  }

[ ... ]

> @@ -465,10 +465,10 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
>  	nspid = jr->load.pid;
>  	pid   = jr_entry_pid(jd, jr);
>  	tid   = jr_entry_tid(jd, jr);
>  	csize = jr->load.code_size;
>  	usize = jd->unwinding_mapped_size;
>  	addr  = jr->load.code_addr;
>  	sym   = (void *)((unsigned long)jr + sizeof(jr->load));

[Severity: High]
This is a pre-existing issue, but is it possible for jr->load.p.total_size
to be smaller than sizeof(jr->load)?

The sym pointer is derived assuming total_size is at least 56 bytes, which
isn't validated before access. Could this lead to an out-of-bounds string
read if a smaller total_size is provided?

>  	code  = (unsigned long)jr + jr->load.p.total_size - csize;

[Severity: Critical]
This is a pre-existing issue, but the code pointer is calculated using csize
without checking if it exceeds total_size.

Could an attacker provide a csize larger than total_size to cause an integer
underflow, resulting in a massive out-of-bounds heap read and information
leak into the generated ELF file?

>  	count = jr->load.code_index;
>  	idr_size = jd->machine->id_hdr_size;
[ ... ]
> @@ -475,10 +475,10 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
>  	event = calloc(1, sizeof(*event) + idr_size);
>  	if (!event)
>  		return -1;
> 
>  	filename = event->mmap2.filename;
>  	size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so",
>  			jd->dir,
>  			nspid,
>  			count);

[Severity: Critical]
This isn't a bug introduced by this patch, but the filename is predictably
constructed using fields (nspid and count) controlled by the JIT dump.

Combined with the lack of O_EXCL|O_NOFOLLOW in jit_emit_elf(), does this
allow an attacker to perform a symlink attack when perf inject is run?

[ ... ]

> @@ -495,10 +495,10 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
>  		jd->nr_debug_entries = 0;
>  	}
> 
>  	if (jd->unwinding_data && jd->eh_frame_hdr_size) {
>  		zfree(&jd->unwinding_data);
>  		jd->eh_frame_hdr_size = 0;
>  		jd->unwinding_mapped_size = 0;
>  		jd->unwinding_size = 0;
>  	}

[Severity: High]
This is a pre-existing issue, but this conditional cleanup leaves
jd->unwinding_data dangling if eh_frame_hdr_size is zero.

If a JIT runtime emits JIT_CODE_UNWINDING_INFO without .eh_frame_hdr, is the
unwinding data incorrectly applied to all subsequent JIT_CODE_LOAD events
until overwritten, producing corrupted ELF files?

[ ... ]

> @@ -665,6 +667,7 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr)
>  
>  	memcpy(data, &jr->info.entries, sz);
>  
> +	zfree(&jd->debug_data);
>  	jd->debug_data       = data;
>  
>  	/*

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260806123604.271277-1-acme@kernel.org?part=2

  reply	other threads:[~2026-08-06 12:52 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-06 12:35 [PATCHES v3 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo
2026-08-06 12:35 ` [PATCH 01/12] perf jitdump: Fix extended header read that always fails Arnaldo Carvalho de Melo
2026-08-06 13:04   ` sashiko-bot
2026-08-06 12:35 ` [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks Arnaldo Carvalho de Melo
2026-08-06 12:52   ` sashiko-bot [this message]
2026-08-06 12:35 ` [PATCH 03/12] perf jitdump: Validate code_size against total_size in code load Arnaldo Carvalho de Melo
2026-08-06 12:56   ` sashiko-bot
2026-08-06 12:35 ` [PATCH 04/12] perf jitdump: Prevent integer underflow in debug info size calculation Arnaldo Carvalho de Melo
2026-08-06 12:55   ` sashiko-bot
2026-08-06 12:35 ` [PATCH 05/12] perf jitdump: Bounds-check debug entry byte-swap loop Arnaldo Carvalho de Melo
2026-08-06 12:51   ` sashiko-bot
2026-08-06 15:21     ` Arnaldo Carvalho de Melo
2026-08-06 12:35 ` [PATCH 06/12] perf jitdump: Check snprintf return before computing header size Arnaldo Carvalho de Melo
2026-08-06 12:52   ` sashiko-bot
2026-08-06 12:35 ` [PATCH 07/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path Arnaldo Carvalho de Melo
2026-08-06 12:51   ` sashiko-bot
2026-08-06 12:35 ` [PATCH 08/12] perf jitdump: Free event in jit_repipe_code_move() Arnaldo Carvalho de Melo
2026-08-06 12:49   ` sashiko-bot
2026-08-06 12:36 ` [PATCH 09/12] perf jitdump: Use dirname() return value in jit_open() Arnaldo Carvalho de Melo
2026-08-06 12:36 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo
2026-08-06 13:10   ` sashiko-bot
2026-08-06 12:36 ` [PATCH 11/12] perf jitdump: Validate sym string NUL-termination in code load Arnaldo Carvalho de Melo
2026-08-06 13:03   ` sashiko-bot
2026-08-06 12:36 ` [PATCH 12/12] perf jitdump: Validate unwinding sizes against record payload Arnaldo Carvalho de Melo
2026-08-06 13:06   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260806125203.3D5E01F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=acme@kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox