summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@bootlin.com>2018-10-18 12:02:50 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-11-10 07:49:47 -0800
commit962bc4202bf0d7ff84deec4cdc6343a103c3c010 (patch)
treee45d568a29439f4a7eb063c1d3a8cee0f226a2a0
parent05d586677df06a8abd499c45321fc6e0e34611e6 (diff)
downloadlinux-stable-962bc4202bf0d7ff84deec4cdc6343a103c3c010.tar.gz
linux-stable-962bc4202bf0d7ff84deec4cdc6343a103c3c010.tar.bz2
linux-stable-962bc4202bf0d7ff84deec4cdc6343a103c3c010.zip
drm/sun4i: Fix an ulong overflow in the dotclock driver
commit e84cb605e02f1b3d0aee8d7157419cd8aaa06038 upstream. The calculated ideal rate can easily overflow an unsigned long, thus making the best div selection buggy as soon as no ideal match is found before the overflow occurs. Fixes: 4731a72df273 ("drm/sun4i: request exact rates to our parents") Cc: <stable@vger.kernel.org> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> Acked-by: Maxime Ripard <maxime.ripard@bootlin.com> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181018100250.12565-1-boris.brezillon@bootlin.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_dotclock.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index e36004fbe453..2a15f2f9271e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -81,9 +81,19 @@ static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
int i;
for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
- unsigned long ideal = rate * i;
+ u64 ideal = (u64)rate * i;
unsigned long rounded;
+ /*
+ * ideal has overflowed the max value that can be stored in an
+ * unsigned long, and every clk operation we might do on a
+ * truncated u64 value will give us incorrect results.
+ * Let's just stop there since bigger dividers will result in
+ * the same overflow issue.
+ */
+ if (ideal > ULONG_MAX)
+ goto out;
+
rounded = clk_hw_round_rate(clk_hw_get_parent(hw),
ideal);