Skip to content

Commit ee4cce0

Browse files
committed
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 <[email protected]> Signed-off-by: Daniel Vetter <[email protected]> Cc: Maarten Lankhorst <[email protected]> Cc: Maxime Ripard <[email protected]> Cc: Thomas Zimmermann <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 36e239b commit ee4cce0

File tree

1 file changed

+38
-11
lines changed

1 file changed

+38
-11
lines changed

drivers/gpu/drm/drm_fb_helper.c

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,27 @@ static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
15371537
}
15381538
}
15391539

1540+
static void __fill_var(struct fb_var_screeninfo *var,
1541+
struct drm_framebuffer *fb)
1542+
{
1543+
int i;
1544+
1545+
var->xres_virtual = fb->width;
1546+
var->yres_virtual = fb->height;
1547+
var->accel_flags = FB_ACCELF_TEXT;
1548+
var->bits_per_pixel = drm_format_info_bpp(fb->format, 0);
1549+
1550+
var->height = var->width = 0;
1551+
var->left_margin = var->right_margin = 0;
1552+
var->upper_margin = var->lower_margin = 0;
1553+
var->hsync_len = var->vsync_len = 0;
1554+
var->sync = var->vmode = 0;
1555+
var->rotate = 0;
1556+
var->colorspace = 0;
1557+
for (i = 0; i < 4; i++)
1558+
var->reserved[i] = 0;
1559+
}
1560+
15401561
/**
15411562
* drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
15421563
* @var: screeninfo to check
@@ -1589,8 +1610,22 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
15891610
return -EINVAL;
15901611
}
15911612

1592-
var->xres_virtual = fb->width;
1593-
var->yres_virtual = fb->height;
1613+
__fill_var(var, fb);
1614+
1615+
/*
1616+
* fb_pan_display() validates this, but fb_set_par() doesn't and just
1617+
* falls over. Note that __fill_var above adjusts y/res_virtual.
1618+
*/
1619+
if (var->yoffset > var->yres_virtual - var->yres ||
1620+
var->xoffset > var->xres_virtual - var->xres)
1621+
return -EINVAL;
1622+
1623+
/* We neither support grayscale nor FOURCC (also stored in here). */
1624+
if (var->grayscale > 0)
1625+
return -EINVAL;
1626+
1627+
if (var->nonstd)
1628+
return -EINVAL;
15941629

15951630
/*
15961631
* 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,
16061641
drm_fb_helper_fill_pixel_fmt(var, format);
16071642
}
16081643

1609-
/*
1610-
* Likewise, bits_per_pixel should be rounded up to a supported value.
1611-
*/
1612-
var->bits_per_pixel = bpp;
1613-
16141644
/*
16151645
* drm fbdev emulation doesn't support changing the pixel format at all,
16161646
* so reject all pixel format changing requests.
@@ -2034,12 +2064,9 @@ static void drm_fb_helper_fill_var(struct fb_info *info,
20342064
}
20352065

20362066
info->pseudo_palette = fb_helper->pseudo_palette;
2037-
info->var.xres_virtual = fb->width;
2038-
info->var.yres_virtual = fb->height;
2039-
info->var.bits_per_pixel = drm_format_info_bpp(format, 0);
2040-
info->var.accel_flags = FB_ACCELF_TEXT;
20412067
info->var.xoffset = 0;
20422068
info->var.yoffset = 0;
2069+
__fill_var(&info->var, fb);
20432070
info->var.activate = FB_ACTIVATE_NOW;
20442071

20452072
drm_fb_helper_fill_pixel_fmt(&info->var, format);

0 commit comments

Comments
 (0)