diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2023-04-04 22:40:38 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2023-04-05 23:43:08 +0300 |
commit | ee4cce0a8f03a3332ccf48ef8b420a65d02d1fcf (patch) | |
tree | 10bf9c7c5f7006630cfc2a08ddc830b0b0181c38 /drivers/gpu | |
parent | 36e239b5d509c1b564669e7ca3d016c444bbf808 (diff) | |
download | linux-ee4cce0a8f03a3332ccf48ef8b420a65d02d1fcf.tar.xz |
drm/fb-helper: fix input validation gaps in check_var
Apparently drivers need to check all this stuff themselves, which for
most things makes sense I guess. And for everything else we luck out,
because modern distros stopped supporting any other fbdev drivers than
drm ones and I really don't want to argue anymore about who needs to
check stuff. Therefore fixing all this just for drm fbdev emulation is
good enough.
Note that var->active is not set or validated. This is just control
flow for fbmem.c and needs to be validated in there as needed.
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20230404194038.472803-3-daniel.vetter@ffwll.ch
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d4b4edde5adc..64458982be40 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1537,6 +1537,27 @@ static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, } } +static void __fill_var(struct fb_var_screeninfo *var, + struct drm_framebuffer *fb) +{ + int i; + + var->xres_virtual = fb->width; + var->yres_virtual = fb->height; + var->accel_flags = FB_ACCELF_TEXT; + var->bits_per_pixel = drm_format_info_bpp(fb->format, 0); + + var->height = var->width = 0; + var->left_margin = var->right_margin = 0; + var->upper_margin = var->lower_margin = 0; + var->hsync_len = var->vsync_len = 0; + var->sync = var->vmode = 0; + var->rotate = 0; + var->colorspace = 0; + for (i = 0; i < 4; i++) + var->reserved[i] = 0; +} + /** * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var * @var: screeninfo to check @@ -1589,8 +1610,22 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, return -EINVAL; } - var->xres_virtual = fb->width; - var->yres_virtual = fb->height; + __fill_var(var, fb); + + /* + * fb_pan_display() validates this, but fb_set_par() doesn't and just + * falls over. Note that __fill_var above adjusts y/res_virtual. + */ + if (var->yoffset > var->yres_virtual - var->yres || + var->xoffset > var->xres_virtual - var->xres) + return -EINVAL; + + /* We neither support grayscale nor FOURCC (also stored in here). */ + if (var->grayscale > 0) + return -EINVAL; + + if (var->nonstd) + return -EINVAL; /* * Workaround for SDL 1.2, which is known to be setting all pixel format @@ -1607,11 +1642,6 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, } /* - * Likewise, bits_per_pixel should be rounded up to a supported value. - */ - var->bits_per_pixel = bpp; - - /* * drm fbdev emulation doesn't support changing the pixel format at all, * so reject all pixel format changing requests. */ @@ -2034,12 +2064,9 @@ static void drm_fb_helper_fill_var(struct fb_info *info, } info->pseudo_palette = fb_helper->pseudo_palette; - info->var.xres_virtual = fb->width; - info->var.yres_virtual = fb->height; - info->var.bits_per_pixel = drm_format_info_bpp(format, 0); - info->var.accel_flags = FB_ACCELF_TEXT; info->var.xoffset = 0; info->var.yoffset = 0; + __fill_var(&info->var, fb); info->var.activate = FB_ACTIVATE_NOW; drm_fb_helper_fill_pixel_fmt(&info->var, format); |