drivers/scsi/scsi_lib.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
scsi_vpd_lun_id() advances through VPD page 0x83 using each descriptor's
length before proving that the descriptor header and body fit in the
retained page. The priority helper and formatters can then read beyond a
truncated descriptor.
Reject pages shorter than the four-byte page header. Track the page end and
stop before calling designator_prio() unless both the descriptor header and
declared body are present.
Fixes: 9983bed3907c ("scsi: Add scsi_vpd_lun_id()")
Signed-off-by: Jiancheng Huang <jchuang@seu.edu.cn>
Assisted-by: Codex:gpt-5.6-luna
---
Changes in v2:
- Add the relevant public mailing lists to Cc; no source changes.
Evidence (v7.2-rc4 KUnit/KASAN oracle under bounded QEMU):
Source: confirmed/scsi_vpd_truncated_designator_sysfs_oob_raw_excerpt.log
[ 2.628665] KTAP version 1
[ 2.628739] 1..1
[ 2.631405] KTAP version 1
[ 2.631565] # Subtest: scsi-vpd-truncated-designator-sysfs
[ 2.631858] # module: scsi_mod
[ 2.632142] 1..1
[ 2.634467] scsi_vpd_truncated_designator_sysfs_test: invoking sdev_show_wwid oracle
[ 2.635065] ==================================================================
[ 2.635366] BUG: KASAN: slab-out-of-bounds in string_escape_mem+0x84d/0xb60
[ 2.635782] Read of size 1 at addr ffff8880019b87e0 by task kunit_try_catch/64
[ 2.635919]
[ 2.635985] CPU: 0 UID: 0 PID: 64 Comm: kunit_try_catch Tainted: G N 7.2.0-rc4-dirty #3 PREEMPT(full)
[ 2.635985] Tainted: [N]=TEST
[ 2.635985] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 2.635985] Call Trace:
[ 2.635985] <TASK>
[ 2.635985] dump_stack_lvl+0x53/0x70
[ 2.635985] print_report+0xd0/0x630
[ 2.635985] ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[ 2.635985] ? string_escape_mem+0x84d/0xb60
[ 2.635985] kasan_report+0xe5/0x120
[ 2.635985] ? string_escape_mem+0x84d/0xb60
[ 2.635985] string_escape_mem+0x84d/0xb60
drivers/scsi/scsi_lib.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index daeb3693f..5e0b84e2d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -3365,7 +3365,7 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
{
u8 cur_id_prio = 0;
u8 cur_id_size = 0;
- const unsigned char *d, *cur_id_str;
+ const unsigned char *d, *cur_id_str, *end;
const struct scsi_vpd *vpd_pg83;
int id_size = -EINVAL;
@@ -3382,11 +3382,21 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
return -EINVAL;
}
+ if (vpd_pg83->len < 4) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+
memset(id, 0, id_len);
- for (d = vpd_pg83->data + 4;
- d < vpd_pg83->data + vpd_pg83->len;
+ end = vpd_pg83->data + vpd_pg83->len;
+ for (d = vpd_pg83->data + 4; end - d >= 4;
d += d[3] + 4) {
- u8 prio = designator_prio(d);
+ u8 prio;
+
+ if (d[3] > end - d - 4)
+ break;
+
+ prio = designator_prio(d);
if (prio == 0 || cur_id_prio > prio)
continue;
--
2.43.0
© 2016 - 2026 Red Hat, Inc.