DragonFlyBSD Kernel Audit
DF-1516 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/i915/intel_overlay.c b/sys/dev/drm/i915/intel_overlay.c
--- a/sys/dev/drm/i915/intel_overlay.c
+++ b/sys/dev/drm/i915/intel_overlay.c
@@ -953,6 +953,7 @@
 	u32 stride_mask;
 	int depth;
 	u32 tmp;
+	uint64_t tmp64;	/* DF-1516: compute in 64-bit to avoid u32 overflow */
 
 	/* check src dimensions */
 	if (IS_I845G(dev_priv) || IS_I830(dev_priv)) {
@@ -1030,8 +1031,11 @@
 		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
 			return -EINVAL;
 
-		tmp = rec->stride_Y*rec->src_height;
-		if (rec->offset_Y + tmp > new_bo->base.size)
+		/* DF-1516: stride_Y*src_height and offset_Y+tmp can wrap as
+		 * u32 additions, fooling the bounds check.  Compute in u64.
+		 */
+		tmp64 = (uint64_t)rec->stride_Y * rec->src_height;
+		if ((uint64_t)rec->offset_Y + tmp64 > new_bo->base.size)
 			return -EINVAL;
 		break;
 
@@ -1041,13 +1045,13 @@
 		if (rec->src_width/uv_hscale > rec->stride_UV)
 			return -EINVAL;
 
-		tmp = rec->stride_Y * rec->src_height;
-		if (rec->offset_Y + tmp > new_bo->base.size)
+		tmp64 = (uint64_t)rec->stride_Y * rec->src_height;
+		if ((uint64_t)rec->offset_Y + tmp64 > new_bo->base.size)
 			return -EINVAL;
 
-		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
-		if (rec->offset_U + tmp > new_bo->base.size ||
-		    rec->offset_V + tmp > new_bo->base.size)
+		tmp64 = (uint64_t)rec->stride_UV * (rec->src_height / uv_vscale);
+		if ((uint64_t)rec->offset_U + tmp64 > new_bo->base.size ||
+		    (uint64_t)rec->offset_V + tmp64 > new_bo->base.size)
 			return -EINVAL;
 		break;
 	}