Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fbdev: Validate info->screen_{base, buffer} in fb_ops implementations

Push the test for info->screen_base from fb_read() and fb_write() into
the implementations of struct fb_ops.{fb_read,fb_write}. In cases where
the driver operates on info->screen_buffer, test this field instead.

While bothi fields, screen_base and screen_buffer, are stored in the
same location, they refer to different address spaces. For correctness,
we want to test each field in exactly the code that uses it.

v2:
* also test screen_base in pvr2fb (Geert)
* also test screen_buffer in ivtvfb, arcfb, broadsheetfb,
hecubafb, metronomefb and ssd1307fb (Geert)
* give a rational for the change (Geert)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: Sui Jingfeng <suijingfeng@loongson.cn>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Helge Deller <deller@gmx.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20230428122452.4856-18-tzimmermann@suse.de

+43 -4
+3
drivers/media/pci/ivtv/ivtvfb.c
··· 378 378 unsigned long dma_size; 379 379 u16 lead = 0, tail = 0; 380 380 381 + if (!info->screen_base) 382 + return -ENODEV; 383 + 381 384 total_size = info->screen_size; 382 385 383 386 if (total_size == 0)
+3
drivers/video/fbdev/arcfb.c
··· 451 451 struct arcfb_par *par; 452 452 unsigned int xres; 453 453 454 + if (!info->screen_buffer) 455 + return -ENODEV; 456 + 454 457 p = *ppos; 455 458 par = info->par; 456 459 xres = info->var.xres;
+3
drivers/video/fbdev/broadsheetfb.c
··· 1013 1013 int err = 0; 1014 1014 unsigned long total_size; 1015 1015 1016 + if (!info->screen_buffer) 1017 + return -ENODEV; 1018 + 1016 1019 total_size = info->fix.smem_len; 1017 1020 1018 1021 if (p > total_size)
+6
drivers/video/fbdev/cobalt_lcdfb.c
··· 129 129 unsigned long pos; 130 130 int len, retval = 0; 131 131 132 + if (!info->screen_base) 133 + return -ENODEV; 134 + 132 135 pos = *ppos; 133 136 if (pos >= LCD_CHARS_MAX || count == 0) 134 137 return 0; ··· 177 174 char dst[LCD_CHARS_MAX]; 178 175 unsigned long pos; 179 176 int len, retval = 0; 177 + 178 + if (!info->screen_base) 179 + return -ENODEV; 180 180 181 181 pos = *ppos; 182 182 if (pos >= LCD_CHARS_MAX || count == 0)
+6
drivers/video/fbdev/core/fb_sys_fops.c
··· 22 22 unsigned long total_size, c; 23 23 ssize_t ret; 24 24 25 + if (!info->screen_buffer) 26 + return -ENODEV; 27 + 25 28 total_size = info->screen_size; 26 29 27 30 if (total_size == 0) ··· 63 60 int err = 0; 64 61 unsigned long total_size, c; 65 62 size_t ret; 63 + 64 + if (!info->screen_buffer) 65 + return -ENODEV; 66 66 67 67 total_size = info->screen_size; 68 68
+8 -2
drivers/video/fbdev/core/fbmem.c
··· 768 768 int c, cnt = 0, err = 0; 769 769 unsigned long total_size, trailing; 770 770 771 - if (!info || ! info->screen_base) 771 + if (!info) 772 772 return -ENODEV; 773 773 774 774 if (info->state != FBINFO_STATE_RUNNING) ··· 776 776 777 777 if (info->fbops->fb_read) 778 778 return info->fbops->fb_read(info, buf, count, ppos); 779 + 780 + if (!info->screen_base) 781 + return -ENODEV; 779 782 780 783 total_size = info->screen_size; 781 784 ··· 839 836 int c, cnt = 0, err = 0; 840 837 unsigned long total_size, trailing; 841 838 842 - if (!info || !info->screen_base) 839 + if (!info) 843 840 return -ENODEV; 844 841 845 842 if (info->state != FBINFO_STATE_RUNNING) ··· 847 844 848 845 if (info->fbops->fb_write) 849 846 return info->fbops->fb_write(info, buf, count, ppos); 847 + 848 + if (!info->screen_base) 849 + return -ENODEV; 850 850 851 851 total_size = info->screen_size; 852 852
+3
drivers/video/fbdev/hecubafb.c
··· 163 163 int err = 0; 164 164 unsigned long total_size; 165 165 166 + if (!info->screen_buffer) 167 + return -ENODEV; 168 + 166 169 total_size = info->fix.smem_len; 167 170 168 171 if (p > total_size)
+3
drivers/video/fbdev/metronomefb.c
··· 523 523 int err = 0; 524 524 unsigned long total_size; 525 525 526 + if (!info->screen_buffer) 527 + return -ENODEV; 528 + 526 529 total_size = info->fix.smem_len; 527 530 528 531 if (p > total_size)
+3
drivers/video/fbdev/pvr2fb.c
··· 647 647 struct page **pages; 648 648 int ret, i; 649 649 650 + if (!info->screen_base) 651 + return -ENODEV; 652 + 650 653 nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT; 651 654 652 655 pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
+2 -2
drivers/video/fbdev/sm712fb.c
··· 1028 1028 int c, i, cnt = 0, err = 0; 1029 1029 unsigned long total_size; 1030 1030 1031 - if (!info || !info->screen_base) 1031 + if (!info->screen_base) 1032 1032 return -ENODEV; 1033 1033 1034 1034 total_size = info->screen_size; ··· 1091 1091 int c, i, cnt = 0, err = 0; 1092 1092 unsigned long total_size; 1093 1093 1094 - if (!info || !info->screen_base) 1094 + if (!info->screen_base) 1095 1095 return -ENODEV; 1096 1096 1097 1097 total_size = info->screen_size;
+3
drivers/video/fbdev/ssd1307fb.c
··· 301 301 void *dst; 302 302 int ret; 303 303 304 + if (!info->screen_buffer) 305 + return -ENODEV; 306 + 304 307 total_size = info->fix.smem_len; 305 308 306 309 if (p > total_size)