From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A341C3F4100; Wed, 5 Aug 2026 21:27:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785965256; cv=none; b=ucgb2iXhbtCREaKHQsDoBza5j+fpQ552X+a/4WpY5mUkWrBPQOuQbaWXcltNaR/40A/LU69TJPKYuU+B0346Bys7lCSgMNP/zVdGT2ltMvVTKIyqhDN7Sfz9uHxZjMhlGj2a97kwaPsrWQiAczgqAlbqxJhe3q03ppmSst909xk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785965256; c=relaxed/simple; bh=+/J9xlSydRSCdHiqZYWd2sDpcpkUtFlKTDmmX8DCnVE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mesprcV48dPM3WMTYsM1Nk3mZ58b9BIYARjZDyjrRQ4Xn4F+uhFT998rb0KOnBBQX4oS6qcrGMr3CbtbFqwal1SkoExMcYX/JFQryg4Qft6Ji+NvqpH+z0XH12vfwaI681nuf0A9SHI5MLeiHJdWWcqW+F1eWY72dn63mrh8UNY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b3RcKTVx; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="b3RcKTVx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A9AAF1F000E9; Wed, 5 Aug 2026 21:27:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785965255; bh=8VgoHQ+EUFWlf9ftGCRRwShE2uFPvLMrq5ebedr1m8U=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=b3RcKTVxIL7cc50yhfX9G4YKG3VvnCzDYea6JwkPN5VdoJERtC0cW8VqJ1QvcAC0f im5KD67U7mxPprXHkLcAT/mhoYAWu4/VXo0L0pi5O30alEvZVKx7cmg7cAHaEMsVwk sYeAubqzv8IR3hWb36R83UfvQyiWcErgf/OTH3bHtOLQdmPcyV/4A1LwVlLa2+N28x KgEnU8F+RjwwrxEE5+PJU6iDWuaLzdXefyIyz3Sj/4k57YxslnMDRCdY4uEICTh5ms kGPMEadVVVzKigfHPrIhVi5/PrGWF0ul1q63imJbL6OrWhrQBsFSzx/UtygFC9CCD/ H+givPW1bQ79w== From: Arnaldo Carvalho de Melo To: Namhyung Kim Cc: Ingo Molnar , Thomas Gleixner , James Clark , Jiri Olsa , Ian Rogers , Adrian Hunter , Clark Williams , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Arnaldo Carvalho de Melo , sashiko-bot , Stephane Eranian Subject: [PATCH 04/12] perf jitdump: Bounds-check debug entry byte-swap loop Date: Wed, 5 Aug 2026 18:26:54 -0300 Message-ID: <20260805212704.267779-5-acme@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260805212704.267779-1-acme@kernel.org> References: <20260805212704.267779-1-acme@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Arnaldo Carvalho de Melo The byte-swap loop for JIT_CODE_DEBUG_INFO uses array indexing (jr->info.entries[n]) to iterate debug entries. struct debug_entry has a flexible array member name[], so each entry has a different size. Array indexing computes offsets assuming fixed-size elements, landing inside variable-length name strings after the first entry and byte-swapping garbage. Additionally, nr_entry is read from untrusted jitdump input without validation against total_size, so a crafted value causes OOB reads. Replace the array indexing with debug_entry_next() pointer arithmetic (which correctly accounts for the variable-length name) and bounds-check each entry against the record's total_size before byte-swapping. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot Cc: Stephane Eranian Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Ian Rogers Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/jitdump.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 787f8a03dae87908..078d3304d2b7ebce 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -318,14 +318,32 @@ jit_get_next_entry(struct jit_buf_desc *jd) switch(id) { case JIT_CODE_DEBUG_INFO: if (jd->needs_bswap) { + void *end = (void *)jr + jr->prefix.total_size; + struct debug_entry *ent; uint64_t n; + jr->info.code_addr = bswap_64(jr->info.code_addr); jr->info.nr_entry = bswap_64(jr->info.nr_entry); - for (n = 0 ; n < jr->info.nr_entry; n++) { - jr->info.entries[n].addr = bswap_64(jr->info.entries[n].addr); - jr->info.entries[n].lineno = bswap_32(jr->info.entries[n].lineno); - jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim); + + /* + * debug_entry has a variable-length name[], so array + * indexing would compute wrong offsets — use + * debug_entry_next() and bounds-check each entry. + */ + ent = &jr->info.entries[0]; + for (n = 0; n < jr->info.nr_entry; n++) { + if ((void *)ent + sizeof(*ent) > end) + break; + /* name must be NUL-terminated within the record */ + if (!memchr(ent->name, '\0', (char *)end - ent->name)) + break; + ent->addr = bswap_64(ent->addr); + ent->lineno = bswap_32(ent->lineno); + ent->discrim = bswap_32(ent->discrim); + ent = debug_entry_next(ent); } + /* clamp so downstream consumers don't overrun */ + jr->info.nr_entry = n; } break; case JIT_CODE_UNWINDING_INFO: -- 2.55.0