DragonFlyBSD Kernel Audit
DF-1340 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/radeon/r600_cs.c b/sys/dev/drm/radeon/r600_cs.c
--- a/sys/dev/drm/radeon/r600_cs.c
+++ b/sys/dev/drm/radeon/r600_cs.c
@@ -351,6 +351,7 @@
 {
 	struct r600_cs_track *track = p->track;
 	u32 slice_tile_max, size, tmp;
+	u64 tmp64;
 	u32 height, height_align, pitch, pitch_align, depth_align;
 	u64 base_offset, base_align;
 	struct array_mode_checker array_check;
@@ -426,21 +427,22 @@
 		return -EINVAL;
 	}
 
-	/* check offset */
-	tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
-	      r600_fmt_get_blocksize(format) * nsamples;
+	/* check offset -- computed in 64-bit to avoid u32 overflow */
+	tmp64 = (u64)r600_fmt_get_nblocksy(format, height) *
+		r600_fmt_get_nblocksx(format, pitch) *
+		r600_fmt_get_blocksize(format) * nsamples;
 	switch (array_mode) {
 	default:
 	case V_0280A0_ARRAY_LINEAR_GENERAL:
 	case V_0280A0_ARRAY_LINEAR_ALIGNED:
-		tmp += track->cb_color_view[i] & 0xFF;
+		tmp64 += track->cb_color_view[i] & 0xFF;
 		break;
 	case V_0280A0_ARRAY_1D_TILED_THIN1:
 	case V_0280A0_ARRAY_2D_TILED_THIN1:
-		tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp;
+		tmp64 += (u64)G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp64;
 		break;
 	}
-	if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
+	if ((tmp64 + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
 		if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
 			/* the initial DDX does bad things with the CB size occasionally */
 			/* it rounds up height too far for slice tile max but the BO is smaller */
@@ -449,9 +451,9 @@
 			 * broken userspace.
 			 */
 		} else {
-			dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",
+			dev_warn(p->dev, "%s offset[%d] %d %llu %llu %lu too big (%d %d) (%d %d %d)\n",
 				 __func__, i, array_mode,
-				 track->cb_color_bo_offset[i], tmp,
+				 track->cb_color_bo_offset[i], tmp64,
 				 radeon_bo_size(track->cb_color_bo[i]),
 				 pitch, height, r600_fmt_get_nblocksx(format, pitch),
 				 r600_fmt_get_nblocksy(format, height),
@@ -517,7 +519,8 @@
 static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
 {
 	struct r600_cs_track *track = p->track;
-	u32 nviews, bpe, ntiles, size, slice_tile_max, tmp;
+	u32 nviews, bpe, ntiles, size, slice_tile_max;
+	u64 tmp;
 	u32 height_align, pitch_align, depth_align;
 	u32 pitch = 8192;
 	u32 height = 8192;
@@ -619,9 +622,9 @@
 
 		ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
 		nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
-		tmp = ntiles * bpe * 64 * nviews * track->nsamples;
+		tmp = (u64)ntiles * bpe * 64 * nviews * track->nsamples;
 		if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
-			dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
+			dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %llu have %lu)\n",
 					array_mode,
 					track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
 					radeon_bo_size(track->db_bo));