DF-2488 / fix.diff
diff --git a/sys/dev/disk/nata/ata-disk.c b/sys/dev/disk/nata/ata-disk.c --- a/sys/dev/disk/nata/ata-disk.c +++ b/sys/dev/disk/nata/ata-disk.c @@ -507,10 +507,30 @@ struct ad_softc *adp = device_get_ivars(dev); u_int8_t *marker, vendor[64], product[64]; - /* try to seperate the ATA model string into vendor and model parts */ - if ((marker = index(atadev->param.model, ' ')) || - (marker = index(atadev->param.model, '-'))) { - int len = (marker - atadev->param.model); + /* try to seperate the ATA model string into vendor and model parts. + * The 40-byte ATA IDENTIFY model field is not guaranteed to be + * NUL-terminated, so search it bounded by the field width (NOT index(), + * which scans until it finds a byte) and clamp len to [0,40] to keep + * strncpy()/vendor[] from operating on a negative (sign-extended to + * ~SIZE_MAX) length. See DF-2488. */ + { + int i; + marker = NULL; + for (i = 0; i < (int)sizeof(atadev->param.model); i++) { + if (atadev->param.model[i] == ' ' || + atadev->param.model[i] == '-') { + marker = &atadev->param.model[i]; + break; + } + } + } + if (marker) { + int len = (int)(marker - atadev->param.model); + + if (len < 0) + len = 0; + else if (len > 40) + len = 40; strncpy(vendor, atadev->param.model, len); vendor[len++] = 0; |