diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index ac9a406250c5..f46393ffd0b5 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,7 +1282,7 @@ 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 -EOVERFLOW. */ int drm_mode_vrefresh(const struct drm_display_mode *mode) { @@ -1293,12 +1294,16 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode) num = mode->clock; den = mode->htotal * mode->vtotal; + unsigned int* tmp = NULL; 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; - if (mode->vscan > 1) - den *= mode->vscan; + den = check_mul_overflow(den,2, tmp) ? -1 : *tmp; + if (mode->vscan > 1){ + 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); }