⬢ DragonFlyBSD Kernel Audit
DF-2420 / fix.diff
← back to finding ↓ download raw
--- 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;