mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									36e239b5d5
								
							
						
					
					
						commit
						ee4cce0a8f
					
				
					 1 changed files with 38 additions and 11 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -1606,11 +1641,6 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 | 
			
		|||
		drm_fb_helper_fill_pixel_fmt(var, format);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * 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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue