DF-2421 / fix.diff
--- a/sys/dev/disk/ahci/ahci_cam.c +++ b/sys/dev/disk/ahci/ahci_cam.c @@ -986,8 +986,11 @@ * Our parallel startup code might have only probed through * to the IDENT, so do the last step if necessary. */ - if (at->at_probe == ATA_PROBE_NEED_IDENT) + if (at->at_probe == ATA_PROBE_NEED_IDENT) { + ahci_os_lock_port(ap); ahci_cam_probe(ap, atx); + ahci_os_unlock_port(ap); + } if (at->at_probe != ATA_PROBE_GOOD) { ccbh->status = CAM_DEV_NOT_THERE; xpt_done(ccb); @@ -1080,7 +1083,13 @@ * XXX not passing NULL at for direct attach! */ xa = ahci_ata_get_xfer(ap, atx); + if (xa == NULL) { + ccbh->status = CAM_RESRC_UNAVAIL; + xpt_done(ccb); + return; + } rdata = (void *)csio->data_ptr; + rdata_len = csio->dxfer_len; /* @@ -1089,6 +1098,19 @@ cdb = (void *)((ccbh->flags & CAM_CDB_POINTER) ? csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes); + /* + * A CAM_DIR_NONE CCB never went through cam_periph_mapmem(), so + * csio->data_ptr is a raw user-supplied pointer which must not be + * dereferenced (bzero/bcopy/DMA) by this driver. + */ + if ((ccbh->flags & CAM_DIR_MASK) == CAM_DIR_NONE && + csio->dxfer_len > 0) { + ccbh->status = CAM_REQ_INVALID; + ahci_ata_put_xfer(xa); + xpt_done(ccb); + return; + } + switch(cdb->generic.opcode) { case REQUEST_SENSE: /* @@ -1522,8 +1544,26 @@ * XXX not passing NULL at for direct attach! */ xa = ahci_ata_get_xfer(ap, atx); + if (xa == NULL) { + ccbh->status = CAM_RESRC_UNAVAIL; + xpt_done(ccb); + return; + } fis = xa->fis; + /* + * A CAM_DIR_NONE CCB never went through cam_periph_mapmem(), so + * csio->data_ptr is a raw user-supplied pointer which must not be + * used for DMA by this driver. + */ + if ((ccbh->flags & CAM_DIR_MASK) == CAM_DIR_NONE && + csio->dxfer_len > 0) { + ccbh->status = CAM_REQ_INVALID; + ahci_ata_put_xfer(xa); + xpt_done(ccb); + return; + } + fis->flags = ATA_H2D_FLAGS_CMD | at->at_target; fis->command = ATA_C_PACKET; fis->device = ATA_H2D_DEVICE_LBA; |