mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jay Vadayath <jay@artiphishell.com>
To: "Martin K. Petersen" <martin.petersen@oracle.com>,
	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org,
	Jay Vadayath <jay@artiphishell.com>
Subject: [PATCH] scsi: sd: validate device-supplied mode sense lengths in cache_type_store
Date: Fri, 17 Jul 2026 12:10:21 -0700	[thread overview]
Message-ID: <20260717191023.15011-1-jay@artiphishell.com> (raw)

A malicious/emulated USB mass storage device (or any SCSI target) can
return a MODE SENSE(6/10) response whose header_length plus
block_descriptor_length is >= the size of the on-stack 64-byte buffer.

cache_type_store() computed
	buffer_data = buffer + data.header_length + data.block_descriptor_length
and then dereferenced buffer_data[0] and buffer_data[2] without ever
checking that this offset still lies within buffer[]. With a reported
block_descriptor_length of 60 and a 4-byte MODE SENSE(6) header the
offset becomes 64 (== sizeof(buffer)), so buffer_data[0]/buffer_data[2]
read and write past the end of the stack buffer. The subsequent length
computation could also underflow and let buffer_data + len run past the
buffer when handed to scsi_mode_select().

KASAN report from an unprivileged user writing to the sysfs cache_type
attribute of a device backed by a raw-gadget mass storage emulator:

  BUG: KASAN: stack-out-of-bounds in cache_type_store+0x8ba/0x8f0
  Read of size 1 at addr ffff888003097c72 by task poc/57
  Call Trace:
   dump_stack_lvl+0x53/0x70
   print_report+0xce/0x610
   kasan_report+0xce/0x100
   cache_type_store+0x8ba/0x8f0
   kernfs_fop_write_iter+0x384/0x4f0
   vfs_write+0x5c7/0xe60
   ksys_write+0xf7/0x1c0
   do_syscall_64+0x61/0x480
   entry_SYSCALL_64_after_hwframe+0x76/0x7e

Reject responses whose mode page offset does not leave room for the
three caching-mode-page bytes we touch, and bound the length by the
space actually remaining in the buffer, mirroring the careful bounds
checking already done in sd_read_cache_type().

This bug was discovered by Artiphishell's vTriage pipeline, which
generated a userspace raw-gadget reproducer that reliably triggers the
KASAN report on an unpatched kernel. The fix below was drafted with the
Claude coding assistant; a userspace reproducer is available on
request.

Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Jay Vadayath <jay@artiphishell.com>

---
 drivers/scsi/sd.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -228,7 +228,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
 	struct scsi_mode_data data;
 	struct scsi_sense_hdr sshdr;
 	static const char temp[] = "temporary ";
-	int len, ret;
+	int len, offset, ret;

 	if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC)
 		/* no cache control on RBC devices; theoretically they
@@ -265,13 +265,22 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
 		return count;
 	}

 	if (scsi_mode_sense(sdp, 0x08, 8, 0, buffer, sizeof(buffer), SD_TIMEOUT,
 			    sdkp->max_retries, &data, NULL))
 		return -EINVAL;
-	len = min_t(size_t, sizeof(buffer), data.length - data.header_length -
-		  data.block_descriptor_length);
-	buffer_data = buffer + data.header_length +
-		data.block_descriptor_length;
+
+	/*
+	 * The mode parameter header and block descriptor lengths are
+	 * supplied by the device and must not be trusted (e.g. a malicious
+	 * USB mass storage device).  Reject responses that would place the
+	 * caching mode page (of which we touch the first three bytes)
+	 * outside of the buffer to avoid an out-of-bounds access below.
+	 */
+	offset = data.header_length + data.block_descriptor_length;
+	if (offset + 3 > sizeof(buffer))
+		return -EINVAL;
+	len = min_t(size_t, sizeof(buffer) - offset, data.length - offset);
+	buffer_data = buffer + offset;
 	buffer_data[2] &= ~0x05;
 	buffer_data[2] |= wce << 2 | rcd;
 	sp = buffer_data[0] & 0x80 ? 1 : 0;

             reply	other threads:[~2026-07-17 19:10 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-17 19:10 Jay Vadayath [this message]
2026-07-17 19:24 ` James Bottomley

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=20260717191023.15011-1-jay@artiphishell.com \
    --to=jay@artiphishell.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    /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