DragonFlyBSD Kernel Audit
DF-1209 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/radeon/r100.c b/sys/dev/drm/radeon/r100.c
--- a/sys/dev/drm/radeon/r100.c
+++ b/sys/dev/drm/radeon/r100.c
@@ -1322,14 +1322,21 @@
 	ib = p->ib.ptr;
 	track = (struct r100_cs_track *)p->track;
 	c = radeon_get_ib_value(p, idx++) & 0x1F;
-	if (c > 16) {
+	/* DF-1209: c == 0 must be rejected. The loop below uses (c - 1) as the
+	 * bound; with c unsigned, c == 0 wraps (c - 1) to UINT_MAX and the loop
+	 * writes unboundedly past track->arrays[16] (cb/zb/aa/textures/slab).
+	 * c == 0 is also nonsensical (LOAD_VBPNTR with zero buffers), so reject
+	 * it alongside the existing c > 16 check. */
+	if (c > 16 || c == 0) {
 	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
 		      pkt->opcode);
 	    radeon_cs_dump_packet(p, pkt);
 	    return -EINVAL;
 	}
 	track->num_arrays = c;
-	for (i = 0; i < (c - 1); i+=2, idx+=3) {
+	/* Guard with i + 1 < c so there is no unsigned underflow even if a
+	 * future caller bypasses the c == 0 check above. */
+	for (i = 0; i + 1 < c; i+=2, idx+=3) {
 		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
 		if (r) {
 			DRM_ERROR("No reloc for packet3 %d\n",