⬢ DragonFlyBSD Kernel Audit
DF-4567 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/i915/intel_guc_ct.c b/sys/dev/drm/i915/intel_guc_ct.c
index 1278f33d..8c64a5cc 100644
--- a/sys/dev/drm/i915/intel_guc_ct.c
+++ b/sys/dev/drm/i915/intel_guc_ct.c
@@ -321,18 +321,24 @@ static int ctb_write(struct intel_guc_ct_buffer *ctb,
 		     bool want_response)
 {
 	struct guc_ct_buffer_desc *desc = ctb->desc;
+	u32 size = PAGE_SIZE / 4;	/* in dwords, fixed by allocation */
 	u32 head = desc->head / 4;	/* in dwords */
 	u32 tail = desc->tail / 4;	/* in dwords */
-	u32 size = desc->size / 4;	/* in dwords */
 	u32 used;			/* in dwords */
 	u32 header;
 	u32 *cmds = ctb->cmds;
 	unsigned int i;
 
-	GEM_BUG_ON(desc->size % 4);
-	GEM_BUG_ON(desc->head % 4);
-	GEM_BUG_ON(desc->tail % 4);
-	GEM_BUG_ON(tail >= size);
+	/*
+	 * The descriptor lives in memory shared with the GuC firmware and
+	 * its fields are firmware-writable.  GEM_BUG_ON() is compiled out
+	 * in production builds, so validate for real before any divide or
+	 * ring arithmetic (desc->size == 0 would panic on % size below).
+	 */
+	if (unlikely(desc->size != size * 4) ||
+	    unlikely(desc->head % 4) || unlikely(head >= size) ||
+	    unlikely(desc->tail % 4) || unlikely(tail >= size))
+		return -EPROTO;
 
 	/*
 	 * tail == head condition indicates empty. GuC FW does not support
@@ -579,19 +585,19 @@ static inline bool ct_header_is_response(u32 header)
 static int ctb_read(struct intel_guc_ct_buffer *ctb, u32 *data)
 {
 	struct guc_ct_buffer_desc *desc = ctb->desc;
+	u32 size = PAGE_SIZE / 4;	/* in dwords, fixed by allocation */
 	u32 head = desc->head / 4;	/* in dwords */
 	u32 tail = desc->tail / 4;	/* in dwords */
-	u32 size = desc->size / 4;	/* in dwords */
 	u32 *cmds = ctb->cmds;
 	s32 available;			/* in dwords */
 	unsigned int len;
 	unsigned int i;
 
-	GEM_BUG_ON(desc->size % 4);
-	GEM_BUG_ON(desc->head % 4);
-	GEM_BUG_ON(desc->tail % 4);
-	GEM_BUG_ON(tail >= size);
-	GEM_BUG_ON(head >= size);
+	/* As in ctb_write(): the descriptor is firmware-writable. */
+	if (unlikely(desc->size != size * 4) ||
+	    unlikely(desc->head % 4) || unlikely(head >= size) ||
+	    unlikely(desc->tail % 4) || unlikely(tail >= size))
+		return -EPROTO;
 
 	/* tail == head condition indicates empty */
 	available = tail - head;