⬢ DragonFlyBSD Kernel Audit
DF-4580 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/radeon_cs.c
+++ b/sys/dev/drm/radeon/radeon_cs.c
@@ -270,6 +270,15 @@
 	u32 ring = RADEON_CS_RING_GFX;
 	s32 priority = 0;
 
+	/* Sanity limit: a CS submission has at most a handful of chunks
+	 * (ib, const ib, relocs, flags).  Anything beyond this is either
+	 * hostile or broken, and the unchecked allocations below turn
+	 * oversized requests into panics or eternal vm_wait() loops on
+	 * DragonFly (GFP_KERNEL == M_WAITOK without M_NULLOK).
+	 */
+	if (cs->num_chunks > 64)
+		return -EINVAL;
+
 	INIT_LIST_HEAD(&p->validated);
 
 	if (!cs->num_chunks) {
@@ -333,6 +342,9 @@
 		}
 
 		size = p->chunks[i].length_dw;
+		/* Bound each chunk's kernel copy too (same rationale). */
+		if (size > 1024 * 1024)
+			return -EINVAL;
 		cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
 		p->chunks[i].user_ptr = cdata;
 		if (user_chunk.chunk_id == RADEON_CHUNK_ID_CONST_IB)
@@ -444,8 +456,10 @@
 	kfree(parser->track);
 	kvfree(parser->relocs);
 	kvfree(parser->vm_bos);
-	for (i = 0; i < parser->nchunks; i++)
-		kvfree(parser->chunks[i].kdata);
+	if (parser->chunks != NULL) {
+		for (i = 0; i < parser->nchunks; i++)
+			kvfree(parser->chunks[i].kdata);
+	}
 	kfree(parser->chunks);
 	kfree(parser->chunks_array);
 	radeon_ib_free(parser->rdev, &parser->ib);