Message ID | 20230802174746.2256-1-astrajoan@yahoo.com (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | [v3] drm/modes: Fix division by zero due to overflow | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Not a local patch |
On Wed, 02 Aug 2023, Ziqi Zhao <astrajoan@yahoo.com> wrote: > In the bug reported by Syzbot, the variable `den == (1 << 22)` and > `mode->vscan == (1 << 10)`, causing the multiplication to overflow and > accidentally make `den == 0`. To prevent any chance of overflow, we > replace `num` and `den` with 64-bit unsigned integers, and explicitly > check if the divisor `den` will overflow. If so, we employ full 64-bit > division with rounding; otherwise we keep the 64-bit to 32-bit division > that could potentially be better optimized. > > In order to minimize the performance overhead, the overflow check for > `den` is wrapped with an `unlikely` condition. Please let me know if > this usage is appropriate. > > Reported-by: syzbot+622bba18029bcde672e1@syzkaller.appspotmail.com > Signed-off-by: Ziqi Zhao <astrajoan@yahoo.com> Reviewed-by: Jani Nikula <jani.nikula@intel.com> > --- > V1 -> V2: address style comments suggested by Jani Nikula > <jani.nikula@linux.intel.com> > V2 -> V3: change title to include context on overflow causing the > division by zero > > drivers/gpu/drm/drm_modes.c | 11 +++++++---- > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c > index ac9a406250c5..137101960690 100644 > --- a/drivers/gpu/drm/drm_modes.c > +++ b/drivers/gpu/drm/drm_modes.c > @@ -1285,13 +1285,13 @@ EXPORT_SYMBOL(drm_mode_set_name); > */ > int drm_mode_vrefresh(const struct drm_display_mode *mode) > { > - unsigned int num, den; > + u64 num, den; > > if (mode->htotal == 0 || mode->vtotal == 0) > return 0; > > - num = mode->clock; > - den = mode->htotal * mode->vtotal; > + num = mul_u32_u32(mode->clock, 1000); > + den = mul_u32_u32(mode->htotal, mode->vtotal); > > if (mode->flags & DRM_MODE_FLAG_INTERLACE) > num *= 2; > @@ -1300,7 +1300,10 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode) > if (mode->vscan > 1) > den *= mode->vscan; > > - return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den); > + if (unlikely(den > UINT_MAX)) > + return DIV64_U64_ROUND_CLOSEST(num, den); > + > + return DIV_ROUND_CLOSEST_ULL(num, (u32) den); > } > EXPORT_SYMBOL(drm_mode_vrefresh);
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index ac9a406250c5..137101960690 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1285,13 +1285,13 @@ EXPORT_SYMBOL(drm_mode_set_name); */ int drm_mode_vrefresh(const struct drm_display_mode *mode) { - unsigned int num, den; + u64 num, den; if (mode->htotal == 0 || mode->vtotal == 0) return 0; - num = mode->clock; - den = mode->htotal * mode->vtotal; + num = mul_u32_u32(mode->clock, 1000); + den = mul_u32_u32(mode->htotal, mode->vtotal); if (mode->flags & DRM_MODE_FLAG_INTERLACE) num *= 2; @@ -1300,7 +1300,10 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode) if (mode->vscan > 1) den *= mode->vscan; - return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den); + if (unlikely(den > UINT_MAX)) + return DIV64_U64_ROUND_CLOSEST(num, den); + + return DIV_ROUND_CLOSEST_ULL(num, (u32) den); } EXPORT_SYMBOL(drm_mode_vrefresh);
In the bug reported by Syzbot, the variable `den == (1 << 22)` and `mode->vscan == (1 << 10)`, causing the multiplication to overflow and accidentally make `den == 0`. To prevent any chance of overflow, we replace `num` and `den` with 64-bit unsigned integers, and explicitly check if the divisor `den` will overflow. If so, we employ full 64-bit division with rounding; otherwise we keep the 64-bit to 32-bit division that could potentially be better optimized. In order to minimize the performance overhead, the overflow check for `den` is wrapped with an `unlikely` condition. Please let me know if this usage is appropriate. Reported-by: syzbot+622bba18029bcde672e1@syzkaller.appspotmail.com Signed-off-by: Ziqi Zhao <astrajoan@yahoo.com> --- V1 -> V2: address style comments suggested by Jani Nikula <jani.nikula@linux.intel.com> V2 -> V3: change title to include context on overflow causing the division by zero drivers/gpu/drm/drm_modes.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)