DragonFlyBSD Kernel Audit
DF-1578 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/hptrr/hptrr_osm_bsd.c b/sys/dev/raid/hptrr/hptrr_osm_bsd.c
--- a/sys/dev/raid/hptrr/hptrr_osm_bsd.c
+++ b/sys/dev/raid/hptrr/hptrr_osm_bsd.c
@@ -579,6 +579,16 @@
 	case INQUIRY:
 		{
 			PINQUIRYDATA inquiryData;
+			/* The fixed offsets written below reach byte 35
+			 * (ProductRevisionLevel[3]); require that the caller
+			 * supplied at least that much buffer space.  Without
+			 * this check a dxfer_len of 0 (or smaller than the
+			 * fields written) corrupts memory past the data
+			 * buffer. */
+			if (ccb->csio.dxfer_len < 36) {
+				ccb->ccb_h.status = CAM_REQ_ABORTED;
+				break;
+			}
 			memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len);
 			inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr;
 
@@ -605,6 +615,13 @@
 		HPT_U8 *rbuf = ccb->csio.data_ptr;
 		HPT_U32 cap;
 
+		/* READ_CAPACITY response is exactly 8 bytes; refuse CCBs that
+		 * did not allocate room for the full response. */
+		if (ccb->csio.dxfer_len < 8) {
+			ccb->ccb_h.status = CAM_REQ_ABORTED;
+			break;
+		}
+
 		if (vd->capacity>0xfffffffful)
 			cap = 0xfffffffful;
 		else
@@ -628,6 +645,13 @@
 		HPT_U8 *rbuf = ccb->csio.data_ptr;
 		HPT_U64	cap = vd->capacity - 1;
 
+		/* SERVICE_ACTION_IN(16) read capacity response is 12 bytes;
+		 * refuse CCBs that did not allocate room for the response. */
+		if (ccb->csio.dxfer_len < 12) {
+			ccb->ccb_h.status = CAM_REQ_ABORTED;
+			break;
+		}
+
 		rbuf[0] = (HPT_U8)(cap>>56);
 		rbuf[1] = (HPT_U8)(cap>>48);
 		rbuf[2] = (HPT_U8)(cap>>40);