[PATCH] scsi: target: bound VPD identifier formatting

Mark Amirkan via B4 Relay <[email protected]>
Newsgroups org.kernel.vger.target-devel,org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.linux-scsi
Message-ID <[email protected]>
From: Mark Amirkan <[email protected]>

transport_set_vpd_ident() formats device-provided VPD page 0x83
identifiers into the 254-byte t10_vpd::device_identifier array without
checking whether the result fits.

A binary identifier emits one type character followed by two hexadecimal
characters per input byte.  A 148-byte identifier therefore emits 297
characters, eventually writing beyond the 296-byte t10_vpd allocation.

Reject binary identifiers longer than 126 bytes and apply the equivalent
destination bound to ASCII and UTF-8 identifiers.  Explicitly terminate
accepted identifiers.  Rejecting instead of truncating avoids creating a
false device identity.

The write was reproduced with generic KASAN on arm64 Linux 7.2-rc7 using
a complete 168-byte VPD response.  With the same input, the fixed kernel
retains the valid NAA descriptor, skips the 148-byte vendor-specific
descriptor, enables the pSCSI backstore, and produces no KASAN report.
Seven boundary tests pass.

The demonstrated path requires a device-provided response and privileged
pSCSI configuration.  No claim is made about exploitability or
unprivileged reachability.

The tested source reproducer is available privately on request.

Fixes: c66ac9db8d4a ("[SCSI] target: Add LIO target core v4.0.0-rc6")
Cc: [email protected]
Assisted-by: Codex:gpt-5.6
Signed-off-by: Mark Amirkan <[email protected]>
---
 drivers/target/target_core_transport.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index dcfe9459..26a0bb66 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1335,6 +1335,14 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83)
 	vpd->device_identifier_code_set = (page_83[0] & 0x0f);
 	switch (vpd->device_identifier_code_set) {
 	case 0x01: /* Binary */
+		/*
+		 * Reserve one character for the type and one for the NUL;
+		 * each binary byte expands to two hex characters.
+		 */
+		if (page_83[3] >
+		    (sizeof(vpd->device_identifier) - 2) / 2)
+			return -EINVAL;
+
 		vpd->device_identifier[j++] =
 				hex_str[vpd->device_identifier_type];
 		while (i < (4 + page_83[3])) {
@@ -1344,11 +1352,16 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83)
 				hex_str[page_83[i] & 0x0f];
 			i++;
 		}
+		vpd->device_identifier[j] = '\0';
 		break;
 	case 0x02: /* ASCII */
 	case 0x03: /* UTF-8 */
+		if (page_83[3] >= sizeof(vpd->device_identifier))
+			return -EINVAL;
+
 		while (i < (4 + page_83[3]))
 			vpd->device_identifier[j++] = page_83[i++];
+		vpd->device_identifier[j] = '\0';
 		break;
 	default:
 		break;

---
base-commit: 3a0dd7ba4f44cdc116d83712f61e7c1a95be3588
change-id: 20260818-pscsi-vpd-ident-bounds-b5ffb129754d

Best regards,
--  
Mark Amirkan <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.