⬢ DragonFlyBSD Kernel Audit
DF-3592 / fix.diff
← back to finding ↓ download raw
--- si.c.orig	2026-09-15 05:59:44.826647602 +0000
+++ si.c.fix3592	2026-09-15 06:01:58.896946431 +0000
@@ -4569,6 +4569,11 @@
 	case PACKET3_ME_WRITE:
 		break;
 	case PACKET3_COPY_DATA:
+			if (pkt->count < 3) {
+				DRM_ERROR("Invalid COPY_DATA packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if ((idx_value & 0xf00) == 0) {
 			reg = ib[idx + 3] * 4;
 			if (!si_vm_reg_valid(reg))
@@ -4576,13 +4581,18 @@
 		}
 		break;
 	case PACKET3_WRITE_DATA:
+			if (pkt->count < 2) {
+				DRM_ERROR("Invalid WRITE_DATA packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if ((idx_value & 0xf00) == 0) {
 			start_reg = ib[idx + 1] * 4;
 			if (idx_value & 0x10000) {
 				if (!si_vm_reg_valid(start_reg))
 					return -EINVAL;
 			} else {
-				for (i = 0; i < (pkt->count - 2); i++) {
+				for (i = 0; i + 2 < pkt->count; i++) {
 					reg = start_reg + (4 * i);
 					if (!si_vm_reg_valid(reg))
 						return -EINVAL;
@@ -4591,6 +4601,11 @@
 		}
 		break;
 	case PACKET3_COND_WRITE:
+			if (pkt->count < 5) {
+				DRM_ERROR("Invalid COND_WRITE packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if (idx_value & 0x100) {
 			reg = ib[idx + 5] * 4;
 			if (!si_vm_reg_valid(reg))
@@ -4598,6 +4613,11 @@
 		}
 		break;
 	case PACKET3_COPY_DW:
+			if (pkt->count < 3) {
+				DRM_ERROR("Invalid COPY_DW packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if (idx_value & 0x2) {
 			reg = ib[idx + 3] * 4;
 			if (!si_vm_reg_valid(reg))
@@ -4620,6 +4640,11 @@
 		}
 		break;
 	case PACKET3_CP_DMA:
+			if (pkt->count < 4) {
+				DRM_ERROR("Invalid CP_DMA packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		r = si_vm_packet3_cp_dma_check(ib, idx);
 		if (r)
 			return r;
@@ -4672,6 +4697,11 @@
 	case PACKET3_ME_WRITE:
 		break;
 	case PACKET3_COPY_DATA:
+			if (pkt->count < 3) {
+				DRM_ERROR("Invalid COPY_DATA packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if ((idx_value & 0xf00) == 0) {
 			reg = ib[idx + 3] * 4;
 			if (!si_vm_reg_valid(reg))
@@ -4679,13 +4709,18 @@
 		}
 		break;
 	case PACKET3_WRITE_DATA:
+			if (pkt->count < 2) {
+				DRM_ERROR("Invalid WRITE_DATA packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if ((idx_value & 0xf00) == 0) {
 			start_reg = ib[idx + 1] * 4;
 			if (idx_value & 0x10000) {
 				if (!si_vm_reg_valid(start_reg))
 					return -EINVAL;
 			} else {
-				for (i = 0; i < (pkt->count - 2); i++) {
+				for (i = 0; i + 2 < pkt->count; i++) {
 					reg = start_reg + (4 * i);
 					if (!si_vm_reg_valid(reg))
 						return -EINVAL;
@@ -4694,6 +4729,11 @@
 		}
 		break;
 	case PACKET3_COND_WRITE:
+			if (pkt->count < 5) {
+				DRM_ERROR("Invalid COND_WRITE packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if (idx_value & 0x100) {
 			reg = ib[idx + 5] * 4;
 			if (!si_vm_reg_valid(reg))
@@ -4701,6 +4741,11 @@
 		}
 		break;
 	case PACKET3_COPY_DW:
+			if (pkt->count < 3) {
+				DRM_ERROR("Invalid COPY_DW packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		if (idx_value & 0x2) {
 			reg = ib[idx + 3] * 4;
 			if (!si_vm_reg_valid(reg))
@@ -4708,6 +4753,11 @@
 		}
 		break;
 	case PACKET3_CP_DMA:
+			if (pkt->count < 4) {
+				DRM_ERROR("Invalid CP_DMA packet3 count: %d\n",
+					pkt->count);
+				return -EINVAL;
+			}
 		r = si_vm_packet3_cp_dma_check(ib, idx);
 		if (r)
 			return r;
@@ -4740,6 +4790,15 @@
 			break;
 		case RADEON_PACKET_TYPE3:
 			pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
+			/* the whole packet must fit within the IB
+			 * (mirrors radeon_cs_packet_parse, radeon_cs.c:768)
+			 */
+			if (pkt.count + 2 > ib->length_dw - idx) {
+				dev_err(rdev->dev, "ib packet too big: idx %d count %d len %d\n",
+					idx, pkt.count, ib->length_dw);
+				ret = -EINVAL;
+				break;
+			}
 			if (ib->is_const_ib)
 				ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt);
 			else {