Date: Thu, 09 Apr 2026 09:18:44 +0000 From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 294354] mfiutil(4)/mrsasutil(4): "show drives" truncates information Message-ID: <bug-294354-227@https.bugs.freebsd.org/bugzilla/>
index | next in thread | raw e-mail
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=294354 Bug ID: 294354 Summary: mfiutil(4)/mrsasutil(4): "show drives" truncates information Product: Base System Version: 14.4-STABLE Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: bin Assignee: bugs@FreeBSD.org Reporter: michaelo@FreeBSD.org On: FreeBSD deblndw014x.innomotics.net 14.4-STABLE FreeBSD 14.4-STABLE c5e1dde24 GENERIC amd64 Consider this output: > # mrsasutil show drives > /dev/mrsas0 Physical Drives: > 4 ( 279G) JBOD <SEAGATE ST9300653SS 5301 serial=6XN1LGJJ\000\000??@> SAS E1:S13 > 5 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2W2A9> SAS E1:S0 > 6 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2W2CT> SAS E1:S1 > 7 ( 279G) JBOD <SEAGATE ST9300605SS 5101 serial=6XP3F4YH\000\000??@> SAS E1:S14 > 8 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2W25E> SAS E1:S2 > 9 ( 279G) JBOD <SEAGATE ST9300653SS 5301 serial=6XN1LGL7\000\000??@> SAS E1:S12 > 10 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2SR8E> SAS E1:S3 > 11 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2W3D2> SAS E1:S7 > 12 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2W2PJ> SAS E1:S4 > 13 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2W3W3> SAS E1:S5 > 14 ( 838G) JBOD <SEAGATE ST9900805SS 5101 serial=6XS2W2HG> SAS E1:S6 > 15 ( 279G) JBOD <SEAGATE ST9300605SS 5101 serial=6XP3F6GJ\000\000??@> SAS E1:S15 On some disks the output looks weird and chopped off. Let's send a SCSI INQUIRY and double check: > root@deblndw014x:~ > # camcontrol cmd da3 -c "12 00 00 00 ff 00" -i 255 -v | hexdump -C > 00000000 00 00 05 12 8b 01 10 02 53 45 41 47 41 54 45 20 |........SEAGATE | > 00000010 53 54 39 33 30 30 36 30 35 53 53 20 20 20 20 20 |ST9300605SS | > 00000020 35 31 30 31 36 58 50 33 46 34 59 48 00 00 00 00 |51016XP3F4YH....| > 00000030 40 23 38 37 39 38 30 00 00 00 00 00 00 00 00 00 |@#87980.........| > 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| > * > 00000060 00 43 6f 70 79 72 69 67 68 74 20 28 63 29 20 32 |.Copyright (c) 2| > 00000070 30 31 31 20 53 65 61 67 61 74 65 20 41 6c 6c 20 |011 Seagate All | > 00000080 72 69 67 68 74 73 20 72 65 73 65 72 76 65 64 20 |rights reserved | > 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| > * > 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |...............| > 000000ff The vendor-specific information is populated with the drive's S/N, followed by four zeros and another identifier which is chopped off by the util. The bug is in mfi_drive.c: > const char * > mfi_pd_inq_string(struct mfi_pd_info *info) > { > struct scsi_inquiry_data iqd, *inq_data = &iqd; > char vendor[16], product[48], revision[16], rstr[12], serial[SID_VENDOR_SPECIFIC_0_SIZE]; > static char inq_string[64]; > > memcpy(inq_data, info->inquiry_data, > (sizeof (iqd) < sizeof (info->inquiry_data))? > sizeof (iqd) : sizeof (info->inquiry_data)); > if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) > return (NULL); > if (SID_TYPE(inq_data) != T_DIRECT) > return (NULL); > if (SID_QUAL(inq_data) != SID_QUAL_LU_CONNECTED) > return (NULL); > > cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor), > sizeof(vendor)); > cam_strvis(product, inq_data->product, sizeof(inq_data->product), > sizeof(product)); > cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision), > sizeof(revision)); > cam_strvis(serial, (char *)inq_data->vendor_specific0, sizeof(inq_data->vendor_specific0), > sizeof(serial)); > > /* Hack for SATA disks, no idea how to tell speed. */ > if (strcmp(vendor, "ATA") == 0) { > snprintf(inq_string, sizeof(inq_string), "<%s %s serial=%s> SATA", > product, revision, serial); > return (inq_string); > } > > switch (SID_ANSI_REV(inq_data)) { > case SCSI_REV_CCS: > strcpy(rstr, "SCSI-CCS"); > break; > case 5: > strcpy(rstr, "SAS"); > break; > default: > snprintf(rstr, sizeof (rstr), "SCSI-%d", > SID_ANSI_REV(inq_data)); > break; > } > snprintf(inq_string, sizeof(inq_string), "<%s %s %s serial=%s> %s", vendor, > product, revision, serial, rstr); > return (inq_string); > } > As far as I understand the code one can first of all reuse SID_VENDOR_SIZE, SID_PRODUCT_SIZE, SID_REVISION_SIZE. Next cam_strvis() is a copy from CAM which deviates from the actual CAM implementation. Since the current code escapes non-printable chars the buffer by SID_VENDOR_SPECIFIC_0_SIZE is quickly depleted. Yet another issue is that all strings created by cam_strvis() are NULL terminated, but are lacking the extra byte (at least serial). inq_string seems to small as well if we calculate SID_VENDOR_SIZE + SID_PRODUCT_SIZE + SID_REVISION_SIZE + SID_VENDOR_SPECIFIC_0_SIZE = 48 + 13 (other chars) = 61 + rstr (11, but realistically 8) = 72 + null byte. Moreover, if we assume that the first three fields are always printable ASCII, we can trim everything except, plus if we cast serial to char * we also assume it to contain ASCII text although the SCSI spec says it is vendor specific, here we could just replace non-printable chars with space. -- You are receiving this mail because: You are the assignee for the bug.home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-294354-227>
