⬢ DragonFlyBSD Kernel Audit
DF-3837 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/evergreen_cs.c
+++ b/sys/dev/drm/radeon/evergreen_cs.c
@@ -3354,6 +3354,24 @@
 	switch (pkt->opcode) {
 	case PACKET3_NOP:
 		break;
+	case PACKET3_COND_WRITE:
+		if (pkt->count != 5) {
+			DRM_ERROR("bad COND_WRITE\n");
+			return -EINVAL;
+		}
+		break;
+	case PACKET3_COPY_DW:
+		if (pkt->count != 4) {
+			DRM_ERROR("bad COPY_DW\n");
+			return -EINVAL;
+		}
+		break;
+	case PACKET3_CP_DMA:
+		if (pkt->count != 4) {
+			DRM_ERROR("bad CP DMA\n");
+			return -EINVAL;
+		}
+		break;
 	case PACKET3_SET_BASE:
 		if (idx_value != 1) {
 			DRM_ERROR("bad SET_BASE");
@@ -3524,6 +3542,11 @@
 
 	do {
 		pkt.idx = idx;
+		if (idx + 1 >= ib->length_dw) {
+			dev_err(rdev->dev, "IB packet at %d doesn't fit (%d)\n",
+				idx, ib->length_dw);
+			return -EINVAL;
+		}
 		pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]);
 		pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]);
 		pkt.one_reg_wr = 0;
@@ -3536,6 +3559,12 @@
 			idx += 1;
 			break;
 		case RADEON_PACKET_TYPE3:
+			if (pkt.idx + pkt.count + 2 > ib->length_dw) {
+				dev_err(rdev->dev,
+					"Packet (%d:%d:%d) end after IB buffer (%d) !\n",
+					pkt.idx, pkt.type, pkt.count, ib->length_dw);
+				return -EINVAL;
+			}
 			pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
 			ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
 			idx += pkt.count + 2;