Passing a maximum as 64-bit type to drm_sysfb_get_validated_int0()
can truncate the value to 32 bits. Use drm_sysfb_get_validated_size0(),
which uses 64-bit arithmetics. Then test the returned stride against
the limits of int to avoid truncations in the returned value. A valid
stride is in the range of [1, INT_MAX] inclusive.

Signed-off-by: Thomas Zimmermann <[email protected]>
Reported-by: Sashiko <[email protected]>
Closes: 
https://lore.kernel.org/dri-devel/[email protected]/
Fixes: 32ae90c66fb6 ("drm/sysfb: Add efidrm for EFI displays")
Fixes: a84eb6abe2b6 ("drm/sysfb: Add vesadrm for VESA displays")
Cc: Thomas Zimmermann <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Cc: [email protected]
Cc: <[email protected]> # v6.16+
---
I've added Reported-by and Closes tags because this is a pre-existing issue.
---
 drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c 
b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
index 042d1b796696..1c479ce0e503 100644
--- a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
+++ b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
@@ -57,11 +57,17 @@ int drm_sysfb_get_stride_si(struct drm_device *dev, const 
struct screen_info *si
                            unsigned int width, unsigned int height, u64 size)
 {
        u64 lfb_linelength = si->lfb_linelength;
+       s64 stride;
 
        if (!lfb_linelength)
                lfb_linelength = drm_format_info_min_pitch(format, 0, width);
 
-       return drm_sysfb_get_validated_int0(dev, "stride", lfb_linelength, 
div64_u64(size, height));
+       stride = drm_sysfb_get_validated_size0(dev, "stride", lfb_linelength,
+                                              div64_u64(size, height));
+       if (stride < INT_MIN || stride > INT_MAX)
+               return -EINVAL;
+
+       return (int)stride; /* stride or negative errno code */
 }
 EXPORT_SYMBOL(drm_sysfb_get_stride_si);
 
-- 
2.54.0

Reply via email to