fix.diff for DF-5768 — clamp the card-derived erase sector size to >= 1. Root cause: sys/bus/mmc/mmc.c derives ivar->erase_sector from card-supplied CSD fields with truncating integer division: SD: mmc.c:1476-1477 ivar->erase_sector = csd.erase_sector * csd.write_bl_len / MMC_SECTOR_SIZE; MMC: mmc.c:1595-1596 (same expression) csd.erase_sector >= 1 and csd.write_bl_len >= 1 are both attacker-chosen (WP_GRP_SIZE/ERASE_GRP_SIZE and WRITE_BL_LEN bit fields of the CSD), so a crafted card with WRITE_BL_LEN bits == 0 (write_bl_len = 1 byte) yields erase_sector == 0. The value flows to mmcsd(4) via MMC_IVAR_ERASE_SECTOR and mmcsd_delete() (sys/dev/disk/mmcsd/mmcsd.c:407-411) divides/modulos by it on the first BIO_FREEBLKS (TRIM) against the device: start = block + erase_sector - 1; start -= start % erase_sector; <-- %0 => #DE => panic Fix: floor the derived value at 1 erase sector (512-byte granularity is guaranteed sane because the driver pins the I/O block length to 512). --- a/sys/bus/mmc/mmc.c +++ b/sys/bus/mmc/mmc.c @@ -1473,8 +1473,8 @@ if (ivar->csd.csd_structure > 0) ivar->high_cap = 1; ivar->tran_speed = ivar->csd.tran_speed; - ivar->erase_sector = ivar->csd.erase_sector * - ivar->csd.write_bl_len / MMC_SECTOR_SIZE; + ivar->erase_sector = MAX(ivar->csd.erase_sector * + ivar->csd.write_bl_len / MMC_SECTOR_SIZE, 1); err = mmc_send_status(sc->dev, sc->dev, ivar->rca, &status); @@ -1592,8 +1592,8 @@ mmc_decode_csd_mmc(ivar->raw_csd, &ivar->csd); ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE; ivar->tran_speed = ivar->csd.tran_speed; - ivar->erase_sector = ivar->csd.erase_sector * - ivar->csd.write_bl_len / MMC_SECTOR_SIZE; + ivar->erase_sector = MAX(ivar->csd.erase_sector * + ivar->csd.write_bl_len / MMC_SECTOR_SIZE, 1); err = mmc_send_status(sc->dev, sc->dev, ivar->rca, &status); if (err != MMC_ERR_NONE) {