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; }