diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -3424,6 +3424,7 @@ u_int64_t lbasize48; u_int32_t lbasize; u_int maxio, d_flags; + size_t tmpsize; dp->secsize = ata_logical_sector_size(&cgd->ident_data); if ((cgd->ident_data.atavalid & ATA_FLAG_54_58) && @@ -3487,10 +3488,25 @@ softc->flags |= ADA_FLAG_UNMAPPEDIO; } softc->disk->d_flags = d_flags; - strlcpy(softc->disk->d_descr, cgd->ident_data.model, - MIN(sizeof(softc->disk->d_descr), sizeof(cgd->ident_data.model))); - strlcpy(softc->disk->d_ident, cgd->ident_data.serial, - MIN(sizeof(softc->disk->d_ident), sizeof(cgd->ident_data.serial))); + + /* + * ata_param_fixup will strip trailing padding spaces and add a NUL, + * but if the field has no padding (as is common for serial numbers) + * there will still be no NUL terminator. We cannot use strlcpy, since + * it keeps reading src until it finds a NUL in order to compute the + * return value (and will truncate the final character due to having a + * single dsize rather than separate ssize and dsize), and strncpy does + * not add a NUL to the destination if it reaches the character limit. + */ + tmpsize = MIN(sizeof(softc->disk->d_descr) - 1, + sizeof(cgd->ident_data.model)); + memcpy(softc->disk->d_descr, cgd->ident_data.model, tmpsize); + softc->disk->d_descr[tmpsize] = '\0'; + + tmpsize = MIN(sizeof(softc->disk->d_ident) - 1, + sizeof(cgd->ident_data.serial)); + memcpy(softc->disk->d_ident, cgd->ident_data.serial, tmpsize); + softc->disk->d_ident[tmpsize] = '\0'; softc->disk->d_sectorsize = softc->params.secsize; softc->disk->d_mediasize = (off_t)softc->params.sectors *