linux-fbdev: Don't overrun the framebuffer when it's larger than expected

We expect a fixed FRAMEBUFFER_SIZE that's width*height*bitdepth, and we
mmap()ed that in.  However, when doing the initial fb clear, we
were using the hardware-provided 'finfo.smem_len' which could be
larger than FRAMEBUFFER_SIZE.  This overran our mmap and triggered
a segfault.

Correct this by mmaping (and clearing) the entire smem_len.  As a safety
measure, panic if smem_len is smaller than our expected FRAMEBUFFER_SIZE

Change-Id: I3222139c7aed6e8e8ee232b1730edd5cd70065ff
This commit is contained in:
Solomon Peachy 2025-05-02 11:29:01 -04:00
parent 5f48d44acf
commit 1f43b14127

View file

@ -69,6 +69,7 @@ void lcd_init_device(void)
vinfo.bits_per_pixel = LCD_DEPTH; vinfo.bits_per_pixel = LCD_DEPTH;
vinfo.xres = LCD_WIDTH; vinfo.xres = LCD_WIDTH;
vinfo.yres = LCD_HEIGHT; vinfo.yres = LCD_HEIGHT;
vinfo.yres_virtual = vinfo.yres; /* Ensure we're on the correct bank */
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) { if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) {
panicf("Cannot set framebuffer to %dx%dx%d", panicf("Cannot set framebuffer to %dx%dx%d",
vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
@ -76,9 +77,11 @@ void lcd_init_device(void)
} }
/* Note: we use a framebuffer size of width*height*bbp. We cannot trust the /* Note: we use a framebuffer size of width*height*bbp. We cannot trust the
* values returned by the driver for line_length */ * values returned by the driver for line_length */
if (finfo.smem_len < FRAMEBUFFER_SIZE)
panicf("FRAMEBUFFER_SIZE too large for hardware? (%u vs %u)", FRAMEBUFFER_SIZE, finfo.smem_len);
/* map framebuffer */ /* map framebuffer */
framebuffer = mmap(NULL, FRAMEBUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); framebuffer = mmap(NULL, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if((void *)framebuffer == MAP_FAILED) if((void *)framebuffer == MAP_FAILED)
{ {
panicf("Cannot map framebuffer"); panicf("Cannot map framebuffer");