Commit 70bbe53c authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Make sure fb gtt offsets stay within 32bits

Let's try to make sure the fb offset computations never hit
an integer overflow by making sure the entire fb stays
below 32bits. framebuffer_check() in the core already does
the same check, but as it doesn't know about tiling some things
can slip through. Repeat the check in the driver with tiling
taken into account.

v2: Use add_overflows() after massaging it to work for me (Chris)
v3: Call it add_overflow_t() to match min_t() & co. (Chris)

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181023160201.9840-1-ville.syrjala@linux.intel.comReviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 1fdee758
...@@ -44,16 +44,19 @@ ...@@ -44,16 +44,19 @@
__stringify(x), (long)(x)) __stringify(x), (long)(x))
#if defined(GCC_VERSION) && GCC_VERSION >= 70000 #if defined(GCC_VERSION) && GCC_VERSION >= 70000
#define add_overflows(A, B) \ #define add_overflows_t(T, A, B) \
__builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0) __builtin_add_overflow_p((A), (B), (T)0)
#else #else
#define add_overflows(A, B) ({ \ #define add_overflows_t(T, A, B) ({ \
typeof(A) a = (A); \ typeof(A) a = (A); \
typeof(B) b = (B); \ typeof(B) b = (B); \
a + b < a; \ (T)(a + b) < a; \
}) })
#endif #endif
#define add_overflows(A, B) \
add_overflows_t(typeof((A) + (B)), (A), (B))
#define range_overflows(start, size, max) ({ \ #define range_overflows(start, size, max) ({ \
typeof(start) start__ = (start); \ typeof(start) start__ = (start); \
typeof(size) size__ = (size); \ typeof(size) size__ = (size); \
......
...@@ -2341,10 +2341,26 @@ static int intel_fb_offset_to_xy(int *x, int *y, ...@@ -2341,10 +2341,26 @@ static int intel_fb_offset_to_xy(int *x, int *y,
int color_plane) int color_plane)
{ {
struct drm_i915_private *dev_priv = to_i915(fb->dev); struct drm_i915_private *dev_priv = to_i915(fb->dev);
unsigned int height;
if (fb->modifier != DRM_FORMAT_MOD_LINEAR && if (fb->modifier != DRM_FORMAT_MOD_LINEAR &&
fb->offsets[color_plane] % intel_tile_size(dev_priv)) fb->offsets[color_plane] % intel_tile_size(dev_priv)) {
DRM_DEBUG_KMS("Misaligned offset 0x%08x for color plane %d\n",
fb->offsets[color_plane], color_plane);
return -EINVAL; return -EINVAL;
}
height = drm_framebuffer_plane_height(fb->height, fb, color_plane);
height = ALIGN(height, intel_tile_height(fb, color_plane));
/* Catch potential overflows early */
if (add_overflows_t(u32, mul_u32_u32(height, fb->pitches[color_plane]),
fb->offsets[color_plane])) {
DRM_DEBUG_KMS("Bad offset 0x%08x or pitch %d for color plane %d\n",
fb->offsets[color_plane], fb->pitches[color_plane],
color_plane);
return -ERANGE;
}
*x = 0; *x = 0;
*y = 0; *y = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment