DragonFlyBSD Kernel Audit
DF-1285 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/hptmv/entry.c b/sys/dev/raid/hptmv/entry.c
--- a/sys/dev/raid/hptmv/entry.c
+++ b/sys/dev/raid/hptmv/entry.c
@@ -2707,6 +2707,17 @@
 			break;
 
 		case INQUIRY:
+			/*
+			 * cam_periph_mapmem() sizes the kernel bounce
+			 * buffer at exactly dxfer_len bytes.  Reject any
+			 * undersized INQUIRY before we write the full
+			 * sizeof(INQUIRYDATA) reply into it; otherwise
+			 * SetInquiryData() overflows the allocation.
+			 */
+			if (csio->dxfer_len < sizeof(INQUIRYDATA)) {
+				ccb_h->status = CAM_REQ_INVALID;
+				break;
+			}
 			ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len);
 			SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev);
 			ccb_h->status = CAM_REQ_CMP;
@@ -2717,6 +2728,11 @@
 			UCHAR *rbuf=csio->data_ptr;
 			unsigned int cap;
 
+			/* READ_CAPACITY reply is 8 bytes (rbuf[0..7]). */
+			if (csio->dxfer_len < 8) {
+				ccb_h->status = CAM_REQ_INVALID;
+				break;
+			}
 			if (pVDev->VDeviceCapacity > 0xfffffffful) {
 				cap = 0xfffffffful;
 			} else {
@@ -2742,6 +2758,11 @@
 			UCHAR *rbuf = csio->data_ptr;
 			LBA_T cap = pVDev->VDeviceCapacity - 1;
 
+			/* SERVICE_ACTION_IN reply is 12 bytes (rbuf[0..11]). */
+			if (csio->dxfer_len < 12) {
+				ccb_h->status = CAM_REQ_INVALID;
+				break;
+			}
 			rbuf[0] = (UCHAR)(cap>>56);
 			rbuf[1] = (UCHAR)(cap>>48);
 			rbuf[2] = (UCHAR)(cap>>40);