DragonFlyBSD Kernel Audit
DF-1311 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/hptiop/hptiop.c b/sys/dev/raid/hptiop/hptiop.c
--- a/sys/dev/raid/hptiop/hptiop.c
+++ b/sys/dev/raid/hptiop/hptiop.c
@@ -68,6 +68,9 @@
 
 #include <dev/raid/hptiop/hptiop.h>
 
+/* Maximum scatter/gather entries the driver will build per request. */
+#define HPTIOP_MAX_SG_COUNT		64
+
 static const char driver_name[] = "hptiop";
 static const char driver_version[] = "v1.8";
 
@@ -1931,6 +1934,8 @@
 	hba->max_devices = iop_config.max_devices;
 	hba->max_request_size = iop_config.request_size;
 	hba->max_sg_count = iop_config.max_sg_count;
+	if (hba->max_sg_count == 0 || hba->max_sg_count > HPTIOP_MAX_SG_COUNT)
+		hba->max_sg_count = HPTIOP_MAX_SG_COUNT;
 
 	if (hba->ops->family == MVFREY_BASED_IOP) {
 		if (hba->ops->internal_memalloc(hba)) {
@@ -2416,7 +2421,10 @@
 
 	if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
 		u_int32_t iop_req32;
-		struct hpt_iop_request_scsi_command req;
+		u_int8_t req_buf[sizeof(struct hpt_iop_request_scsi_command) +
+			(HPTIOP_MAX_SG_COUNT - 1) * sizeof(struct hpt_iopsg)];
+		struct hpt_iop_request_scsi_command *req =
+			(struct hpt_iop_request_scsi_command *)req_buf;
 
 		iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue);
 
@@ -2430,7 +2438,7 @@
 		}
 
 		if (ccb->csio.dxfer_len && nsegs > 0) {
-			struct hpt_iopsg *psg = req.sg_list;
+			struct hpt_iopsg *psg = req->sg_list;
 			for (idx = 0; idx < nsegs; idx++, psg++) {
 				psg->pci_address = (u_int64_t)segs[idx].ds_addr;
 				psg->size = segs[idx].ds_len;
@@ -2439,22 +2447,22 @@
 			psg[-1].eot = 1;
 		}
 
-		bcopy(cdb, req.cdb, ccb->csio.cdb_len);
+		bcopy(cdb, req->cdb, min(ccb->csio.cdb_len, sizeof(req->cdb)));
 
-		req.header.size =
+		req->header.size =
 				offsetof(struct hpt_iop_request_scsi_command, sg_list)
 				+ nsegs*sizeof(struct hpt_iopsg);
-		req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
-		req.header.flags = 0;
-		req.header.result = IOP_RESULT_PENDING;
-		req.header.context = (u_int64_t)(unsigned long)srb;
-		req.dataxfer_length = ccb->csio.dxfer_len;
-		req.channel =  0;
-		req.target =  ccb->ccb_h.target_id;
-		req.lun =  ccb->ccb_h.target_lun;
+		req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
+		req->header.flags = 0;
+		req->header.result = IOP_RESULT_PENDING;
+		req->header.context = (u_int64_t)(unsigned long)srb;
+		req->dataxfer_length = ccb->csio.dxfer_len;
+		req->channel =  0;
+		req->target =  ccb->ccb_h.target_id;
+		req->lun =  ccb->ccb_h.target_lun;
 
 		bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32,
-			(u_int8_t *)&req, req.header.size);
+			(u_int8_t *)req, req->header.size);
 
 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 			bus_dmamap_sync(hba->io_dmat,