All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavitra Jha <jhapavitra98@gmail.com>
To: Sven Peter <sven@kernel.org>, Janne Grunau <j@jannau.net>
Cc: Neal Gompa <neal@gompa.dev>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org,
	Pavitra Jha <jhapavitra98@gmail.com>,
	stable@vger.kernel.org
Subject: [PATCH] soc: apple: rtkit: fix OOB reads in crashlog parser
Date: Fri, 31 Jul 2026 12:52:10 -0400	[thread overview]
Message-ID: <20260731165210.113227-1-jhapavitra98@gmail.com> (raw)

apple_rtkit_crashlog_dump() parses a binary blob copied from a shared
memory region populated by the RTKit coprocessor after a crash. The
blob is treated as trusted structured data, but four distinct bugs
allow a malicious or compromised coprocessor to trigger out-of-bounds
reads against the kernel heap:

1. Section header read without tail-space guard
   The main loop is guarded by (offset < size), but the section header
   occupies bytes [offset, offset+16). A section starting within the
   last 15 bytes of the buffer causes the memcpy at offset+12 to read
   past the end of the allocation.

2. section_size not validated against remaining buffer space
   section_size is a u32 read verbatim from the coprocessor blob.
   It is passed directly to each handler as the 'size' argument without
   checking offset + section_size <= size. Every handler therefore
   operates on memory past the end of the shadow buffer. Additionally,
   section_size == 0 causes an infinite loop because offset never
   advances.

3. dump_mailbox: size_t underflow when section_size < 28
   n_messages = (size - 28) / sizeof(entry) performs size_t arithmetic.
   If the coprocessor reports section_size < 28, the subtraction wraps
   to ~0UL, n_messages becomes enormous, and the subsequent memcpy loop
   reads and dev_warn-logs arbitrary adjacent slab memory, constituting
   a kernel heap info-leak.

KASAN confirmed (kernel 7.1.0, QEMU/x86_64, kasan_multi_shot):

  BUG: KASAN: slab-out-of-bounds in apple_rtkit_crashlog_dump.cold
  Read of size 24 at addr ffff88800469f08c by task insmod/60

  Call Trace:
    kasan_check_range
    __asan_memcpy
    apple_rtkit_crashlog_dump.cold
    rtkit_poc_init

4. dump_version and dump_str: bare %s with no NUL guarantee
   dump_version() ignores its size argument entirely and passes bfr+16
   directly to dev_warn() as a %s argument. If section_size places the
   section end before a NUL byte, dev_warn walks arbitrarily past the
   allocation. dump_str() has the same issue in its else branch: memchr
   correctly bounds the search, but the resulting pointer is then passed
   to dev_warn() as %s without a NUL guarantee within the real buffer.

Fix:
- Check offset + 16 <= size before reading each section header.
- Reject section_size < 16 or offset + section_size > size before
  dispatching, ensuring every handler receives a size bounded by the
  real buffer. This also eliminates the infinite-loop case.
- Add an explicit size < 28 guard in dump_mailbox() to prevent the
  size_t underflow regardless of the outer check.
- Replace bare %s with %.*s in dump_version() and the else branch of
  dump_str(), using the (now validated) size argument as the bound.

Attacker model: any entity able to influence RTKit coprocessor firmware
or crash-log shared memory (coprocessor compromise, DMA-capable
peripheral on the same interconnect) can trigger these bugs against any
Linux system running Asahi Linux on Apple Silicon hardware.

Fixes: 9bd1d9a0d8bb ("soc: apple: Add RTKit IPC library")
Cc: stable@vger.kernel.org
Signed-off-by: Pavitra Jha <jhapavitra98@gmail.com>
---
 drivers/soc/apple/rtkit-crashlog.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/apple/rtkit-crashlog.c b/drivers/soc/apple/rtkit-crashlog.c
index 8319e3651..3af17c31d 100644
--- a/drivers/soc/apple/rtkit-crashlog.c
+++ b/drivers/soc/apple/rtkit-crashlog.c
@@ -81,8 +81,8 @@ static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,
 			*newline = tmp;
 			ptr = newline + 1;
 		} else {
-			dev_warn(rtk->dev, "RTKit: Message (id=%x): %s", idx,
-				 ptr);
+			dev_warn(rtk->dev, "RTKit: Message (id=%x): %.*s", idx,
+				 (int)(end - ptr), ptr);
 			break;
 		}
 	}
@@ -91,7 +91,12 @@ static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,
 static void apple_rtkit_crashlog_dump_version(struct apple_rtkit *rtk, u8 *bfr,
 					      size_t size)
 {
-	dev_warn(rtk->dev, "RTKit: Version: %s", bfr + 16);
+	if (size < 17) {
+		dev_warn(rtk->dev, "RTKit: Version section too small: 0x%zx",
+			 size);
+		return;
+	}
+	dev_warn(rtk->dev, "RTKit: Version: %.*s", (int)(size - 16), bfr + 16);
 }
 
 static void apple_rtkit_crashlog_dump_time(struct apple_rtkit *rtk, u8 *bfr,
@@ -112,6 +117,11 @@ static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr,
 
 	memcpy(&type, bfr + 16, 4);
 	memcpy(&index, bfr + 24, 4);
+	if (size < 28) {
+		dev_warn(rtk->dev, "RTKit: Mailbox section too small: 0x%zx",
+			 size);
+		return;
+	}
 	n_messages = (size - 28) / sizeof(entry);
 
 	dev_warn(rtk->dev, "RTKit: Mailbox history (type = %d, index = %d)",
@@ -206,8 +216,20 @@ void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
 	offset = sizeof(header);
 
 	while (offset < size) {
+		if (offset + 16 > size) {
+			dev_warn(rtk->dev,
+				 "RTKit: Crashlog section header out of bounds at 0x%zx",
+				 offset);
+			break;
+		}
 		memcpy(&section_fourcc, bfr + offset, 4);
 		memcpy(&section_size, bfr + offset + 12, 4);
+		if (section_size < 16 || offset + section_size > size) {
+			dev_warn(rtk->dev,
+				 "RTKit: Crashlog section size out of bounds: %u at 0x%zx",
+				 section_size, offset);
+			break;
+		}
 
 		switch (section_fourcc) {
 		case APPLE_RTKIT_CRASHLOG_HEADER:
-- 
2.53.0


                 reply	other threads:[~2026-07-31 16:53 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260731165210.113227-1-jhapavitra98@gmail.com \
    --to=jhapavitra98@gmail.com \
    --cc=asahi@lists.linux.dev \
    --cc=gregkh@linuxfoundation.org \
    --cc=j@jannau.net \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=neal@gompa.dev \
    --cc=stable@vger.kernel.org \
    --cc=sven@kernel.org \
    /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 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.