]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fbdev: defio: Keep module reference from VMAs
authorThomas Zimmermann <tzimmermann@suse.de>
Tue, 24 Feb 2026 08:25:55 +0000 (09:25 +0100)
committerHelge Deller <deller@gmx.de>
Mon, 9 Mar 2026 12:06:48 +0000 (13:06 +0100)
Acquire a module reference on each mmap and VMA open; hold it until
the kernel closes the VMA. Protects against unloading the module
while user space still has a mapping of the graphics memory. The
VMA page-fault handling would then call into undefined code.

This situation can happen if the underlying device has been unplugged
and the driver has been unloaded. It would then be possible to trigger
the bug by unloading the fbdev core module.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Helge Deller <deller@gmx.de>
drivers/video/fbdev/core/fb_defio.c

index 93bd2f696fa475493b60ceb161986124aed07871..56030eb42f71429857acc44bcb7a8a0365e36abc 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/export.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -83,6 +84,7 @@ static void fb_deferred_io_vm_open(struct vm_area_struct *vma)
 {
        struct fb_deferred_io_state *fbdefio_state = vma->vm_private_data;
 
+       WARN_ON_ONCE(!try_module_get(THIS_MODULE));
        fb_deferred_io_state_get(fbdefio_state);
 }
 
@@ -91,6 +93,7 @@ static void fb_deferred_io_vm_close(struct vm_area_struct *vma)
        struct fb_deferred_io_state *fbdefio_state = vma->vm_private_data;
 
        fb_deferred_io_state_put(fbdefio_state);
+       module_put(THIS_MODULE);
 }
 
 static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long offs)
@@ -335,6 +338,9 @@ int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
        vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
 
+       if (!try_module_get(THIS_MODULE))
+               return -EINVAL;
+
        vma->vm_ops = &fb_deferred_io_vm_ops;
        vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
        if (!(info->flags & FBINFO_VIRTFB))