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 2BE5146F4BE; Wed, 5 Aug 2026 13:31:34 +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=1785936696; cv=none; b=Stf7AOtlcwrgSFPs+Vir5sj95IqRpDAxUO5xc0tgNVj/WnIA9fEZz5WKQIK4mZEb/A8cwJ76OTP/PfxJoEG/upssir6CygiDjwLZXJWaGHtE4ZqYMz8lL7W78vfNoAErvZQcVIJvYQUOJZSDgsu2p3QQtsbBgI0eHuxYL0sHBrc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785936696; c=relaxed/simple; bh=LLtfsq5IdqVNqzBiw7K0Qlaj1ChTEE+Zcuowt8R4cPI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qarQJyGP+eo07m+lk14pSgqcym0TyqlCxtO6Plo1VTh66Z9WgdxhKU+yjPpKQRb1Iz+kcKFXifGCqRFd4P791lRp5fmPGrDSvD+8tAswPIfFTBN7/sE8ILgkL/MvkrmsiTCCOlSHilo5yS1njtUtHXAIkLlsVPbSxpkVc+jejxw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gGbtsiB9; 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="gGbtsiB9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9249C1F00A3D; Wed, 5 Aug 2026 13:31:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785936694; bh=ZVKRz2nkvbsV2c2B+Exqm/qaG3jK1ceYpyVXldsTxSA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=gGbtsiB9+DQY6dxIeyM8ba3ULGnCmT8wIxxISZcuHxpXP2nZDz8eukWoBTRt1ml4Z ExrR0Dt11veSv/lDN5j+51eFiWK34noydPacss2dX4DbmWiX7cP/wxUtxcgnZJzs7G k0544SF/K+okYiAAVwOR4wkAC5bV4rXOfzWWOH0e+5Rxg2SknLhS8VdgcFXdRBP/Vb BjqJ3aXhr/v/BXJ5028d+vJZPU/OXZOxZ3Zy+1A1QrhiPc4DSOBgdFkXhWXRbDlfPV e8N4PDuwqKHWG9RqdKlVMpNpSwEX8JVlYRrcjhvLngFGp5s1sPhKwOCMfYhaegUsEq K2eGJEueiBNOg== 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 10:30:03 -0300 Message-ID: <20260805133013.235016-5-acme@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260805133013.235016-1-acme@kernel.org> References: <20260805133013.235016-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 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