diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index ac9a406250c5..32c1d95ef1a7 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -30,6 +30,7 @@ * authorization from the copyright holder(s) and author(s). */ +#include "linux/overflow.h" #include #include #include /* for KHZ2PICOS() */ @@ -1281,24 +1282,28 @@ EXPORT_SYMBOL(drm_mode_set_name); * * Returns: * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the - * value first if it is not yet set. + * value first if it is not yet set. If the result overflows, returns 0. */ int drm_mode_vrefresh(const struct drm_display_mode *mode) { unsigned int num, den; + unsigned int* tmp = NULL; if (mode->htotal == 0 || mode->vtotal == 0) return 0; num = mode->clock; - den = mode->htotal * mode->vtotal; + den = check_mul_overflow(mode->htotal, mode->vtotal, tmp) ? -1 : *tmp; if (mode->flags & DRM_MODE_FLAG_INTERLACE) - num *= 2; + num = check_mul_overflow(num,2, tmp) ? -1 : *tmp; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - den *= 2; + den = check_mul_overflow(den,2, tmp) ? -1 : *tmp; if (mode->vscan > 1) - den *= mode->vscan; + num = check_mul_overflow(den, mode->vscan, tmp) ? -1 : *tmp; + + if(den == -1 || num == -1) + return 0; return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den); }