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
This commit is contained in:
@@ -378,6 +378,9 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
|
||||
unsigned long dma_size;
|
||||
u16 lead = 0, tail = 0;
|
||||
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->screen_size;
|
||||
|
||||
if (total_size == 0)
|
||||
|
||||
@@ -451,6 +451,9 @@ static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
|
||||
struct arcfb_par *par;
|
||||
unsigned int xres;
|
||||
|
||||
if (!info->screen_buffer)
|
||||
return -ENODEV;
|
||||
|
||||
p = *ppos;
|
||||
par = info->par;
|
||||
xres = info->var.xres;
|
||||
|
||||
@@ -1013,6 +1013,9 @@ static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
|
||||
int err = 0;
|
||||
unsigned long total_size;
|
||||
|
||||
if (!info->screen_buffer)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->fix.smem_len;
|
||||
|
||||
if (p > total_size)
|
||||
|
||||
@@ -129,6 +129,9 @@ static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
|
||||
unsigned long pos;
|
||||
int len, retval = 0;
|
||||
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
pos = *ppos;
|
||||
if (pos >= LCD_CHARS_MAX || count == 0)
|
||||
return 0;
|
||||
@@ -175,6 +178,9 @@ static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
|
||||
unsigned long pos;
|
||||
int len, retval = 0;
|
||||
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
pos = *ppos;
|
||||
if (pos >= LCD_CHARS_MAX || count == 0)
|
||||
return 0;
|
||||
|
||||
@@ -22,6 +22,9 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count,
|
||||
unsigned long total_size, c;
|
||||
ssize_t ret;
|
||||
|
||||
if (!info->screen_buffer)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->screen_size;
|
||||
|
||||
if (total_size == 0)
|
||||
@@ -61,6 +64,9 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
|
||||
unsigned long total_size, c;
|
||||
size_t ret;
|
||||
|
||||
if (!info->screen_buffer)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->screen_size;
|
||||
|
||||
if (total_size == 0)
|
||||
|
||||
@@ -768,7 +768,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
int c, cnt = 0, err = 0;
|
||||
unsigned long total_size, trailing;
|
||||
|
||||
if (!info || ! info->screen_base)
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
if (info->state != FBINFO_STATE_RUNNING)
|
||||
@@ -777,6 +777,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
if (info->fbops->fb_read)
|
||||
return info->fbops->fb_read(info, buf, count, ppos);
|
||||
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->screen_size;
|
||||
|
||||
if (total_size == 0)
|
||||
@@ -836,7 +839,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
int c, cnt = 0, err = 0;
|
||||
unsigned long total_size, trailing;
|
||||
|
||||
if (!info || !info->screen_base)
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
if (info->state != FBINFO_STATE_RUNNING)
|
||||
@@ -845,6 +848,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
if (info->fbops->fb_write)
|
||||
return info->fbops->fb_write(info, buf, count, ppos);
|
||||
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->screen_size;
|
||||
|
||||
if (total_size == 0)
|
||||
|
||||
@@ -163,6 +163,9 @@ static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
|
||||
int err = 0;
|
||||
unsigned long total_size;
|
||||
|
||||
if (!info->screen_buffer)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->fix.smem_len;
|
||||
|
||||
if (p > total_size)
|
||||
|
||||
@@ -523,6 +523,9 @@ static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
|
||||
int err = 0;
|
||||
unsigned long total_size;
|
||||
|
||||
if (!info->screen_buffer)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->fix.smem_len;
|
||||
|
||||
if (p > total_size)
|
||||
|
||||
@@ -647,6 +647,9 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
|
||||
struct page **pages;
|
||||
int ret, i;
|
||||
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
|
||||
pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
|
||||
|
||||
@@ -1028,7 +1028,7 @@ static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
|
||||
int c, i, cnt = 0, err = 0;
|
||||
unsigned long total_size;
|
||||
|
||||
if (!info || !info->screen_base)
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->screen_size;
|
||||
@@ -1091,7 +1091,7 @@ static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
|
||||
int c, i, cnt = 0, err = 0;
|
||||
unsigned long total_size;
|
||||
|
||||
if (!info || !info->screen_base)
|
||||
if (!info->screen_base)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->screen_size;
|
||||
|
||||
@@ -301,6 +301,9 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
|
||||
void *dst;
|
||||
int ret;
|
||||
|
||||
if (!info->screen_buffer)
|
||||
return -ENODEV;
|
||||
|
||||
total_size = info->fix.smem_len;
|
||||
|
||||
if (p > total_size)
|
||||
|
||||
Reference in New Issue
Block a user