Skip site navigation (1)Skip section navigation (2)
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>