lkml.org 
[lkml]   [2022]   [May]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [PATCH v2] fbdev: Use helper to get fb_info in all file operations
From
Hi

Am 04.05.22 um 11:02 schrieb Daniel Vetter:
> On Tue, May 03, 2022 at 10:19:34PM +0200, Javier Martinez Canillas wrote:
>> A reference to the framebuffer device struct fb_info is stored in the file
>> private data, but this reference could no longer be valid and must not be
>> accessed directly. Instead, the file_fb_info() accessor function must be
>> used since it does sanity checking to make sure that the fb_info is valid.
>>
>> This can happen for example if the registered framebuffer device is for a
>> driver that just uses a framebuffer provided by the system firmware. In
>> that case, the fbdev core would unregister the framebuffer device when a
>> real video driver is probed and ask to remove conflicting framebuffers.
>>
>> Most fbdev file operations already use the helper to get the fb_info but
>> get_fb_unmapped_area() and fb_deferred_io_fsync() don't. Fix those two.
>>
>> Since fb_deferred_io_fsync() is not in fbmem.o, the helper has to be
>> exported. Rename it and add a fb_ prefix to denote that is public now.
>>
>> Reported-by: Junxiao Chang <junxiao.chang@intel.com>
>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
>
> Note that fb_file_info is hilariously racy since there's nothing
> preventing a concurrenct framebuffer_unregister. Or at least I'm not
> seeing anything. See cf4a3ae4ef33 ("fbdev: lock_fb_info cannot fail") for
> context, maybe reference that commit here in your patch.

Can we acquire registration_lock around [1]?

[1]
https://elixir.bootlin.com/linux/v5.17.5/source/drivers/video/fbdev/core/fbmem.c#L756

>
> Either way this doesn't really make anything worse, so
> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
> Cheers, Daniel
>
>> ---
>>
>> Changes in v2:
>> - Fix copy & paste error passing file->private_data instead of file
>> to fb_file_fb_info() function (Sam Ravnborg).
>>
>> drivers/video/fbdev/core/fb_defio.c | 5 ++++-
>> drivers/video/fbdev/core/fbmem.c | 24 +++++++++++++++---------
>> include/linux/fb.h | 1 +
>> 3 files changed, 20 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
>> index 842c66b3e33d..ccdf903c48bd 100644
>> --- a/drivers/video/fbdev/core/fb_defio.c
>> +++ b/drivers/video/fbdev/core/fb_defio.c
>> @@ -68,12 +68,15 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
>>
>> int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
>> {
>> - struct fb_info *info = file->private_data;
>> + struct fb_info *info = fb_file_fb_info(file);
>> struct inode *inode = file_inode(file);
>> int err = file_write_and_wait_range(file, start, end);
>> if (err)
>> return err;
>>
>> + if (!info)
>> + return -ENODEV;
>> +
>> /* Skip if deferred io is compiled-in but disabled on this fbdev */
>> if (!info->fbdefio)
>> return 0;
>> diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
>> index 97eb0dee411c..ba2c14a1087d 100644
>> --- a/drivers/video/fbdev/core/fbmem.c
>> +++ b/drivers/video/fbdev/core/fbmem.c
>> @@ -745,7 +745,7 @@ static const struct seq_operations __maybe_unused proc_fb_seq_ops = {
>> * So look up the fb_info using the inode minor number,
>> * and just verify it against the reference we have.
>> */
>> -static struct fb_info *file_fb_info(struct file *file)
>> +struct fb_info *fb_file_fb_info(struct file *file)
>> {
>> struct inode *inode = file_inode(file);
>> int fbidx = iminor(inode);
>> @@ -755,12 +755,13 @@ static struct fb_info *file_fb_info(struct file *file)
>> info = NULL;
>> return info;
>> }
>> +EXPORT_SYMBOL(fb_file_fb_info);
>>
>> static ssize_t
>> fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
>> {
>> unsigned long p = *ppos;
>> - struct fb_info *info = file_fb_info(file);
>> + struct fb_info *info = fb_file_fb_info(file);
>> u8 *buffer, *dst;
>> u8 __iomem *src;
>> int c, cnt = 0, err = 0;
>> @@ -825,7 +826,7 @@ static ssize_t
>> fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
>> {
>> unsigned long p = *ppos;
>> - struct fb_info *info = file_fb_info(file);
>> + struct fb_info *info = fb_file_fb_info(file);
>> u8 *buffer, *src;
>> u8 __iomem *dst;
>> int c, cnt = 0, err = 0;
>> @@ -1181,7 +1182,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
>>
>> static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>> {
>> - struct fb_info *info = file_fb_info(file);
>> + struct fb_info *info = fb_file_fb_info(file);
>>
>> if (!info)
>> return -ENODEV;
>> @@ -1293,7 +1294,7 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
>> static long fb_compat_ioctl(struct file *file, unsigned int cmd,
>> unsigned long arg)
>> {
>> - struct fb_info *info = file_fb_info(file);
>> + struct fb_info *info = fb_file_fb_info(file);
>> const struct fb_ops *fb;
>> long ret = -ENOIOCTLCMD;
>>
>> @@ -1333,7 +1334,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
>> static int
>> fb_mmap(struct file *file, struct vm_area_struct * vma)
>> {
>> - struct fb_info *info = file_fb_info(file);
>> + struct fb_info *info = fb_file_fb_info(file);
>> int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma);
>> unsigned long mmio_pgoff;
>> unsigned long start;
>> @@ -1434,7 +1435,7 @@ fb_release(struct inode *inode, struct file *file)
>> __acquires(&info->lock)
>> __releases(&info->lock)
>> {
>> - struct fb_info * const info = file_fb_info(file);
>> + struct fb_info * const info = fb_file_fb_info(file);
>>
>> if (!info)
>> return -ENODEV;
>> @@ -1453,8 +1454,13 @@ unsigned long get_fb_unmapped_area(struct file *filp,
>> unsigned long addr, unsigned long len,
>> unsigned long pgoff, unsigned long flags)
>> {
>> - struct fb_info * const info = filp->private_data;
>> - unsigned long fb_size = PAGE_ALIGN(info->fix.smem_len);
>> + struct fb_info * const info = fb_file_fb_info(filp);
>> + unsigned long fb_size;
>> +
>> + if (!info)
>> + return -ENODEV;
>> +
>> + fb_size = PAGE_ALIGN(info->fix.smem_len);
>>
>> if (pgoff > fb_size || len > fb_size - pgoff)
>> return -EINVAL;
>> diff --git a/include/linux/fb.h b/include/linux/fb.h
>> index 9a77ab615c36..3004b8b8c5c2 100644
>> --- a/include/linux/fb.h
>> +++ b/include/linux/fb.h
>> @@ -624,6 +624,7 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var,
>> struct fb_fix_screeninfo *fix);
>> extern int fb_get_options(const char *name, char **option);
>> extern int fb_new_modelist(struct fb_info *info);
>> +extern struct fb_info *fb_file_fb_info(struct file *file);
>>
>> extern struct fb_info *registered_fb[FB_MAX];
>> extern int num_registered_fb;
>> --
>> 2.35.1
>>
>

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev
[unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2022-05-04 11:28    [W:0.080 / U:0.288 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site