From 3d0374cbf367475eb46fa16b18dab985a97f020c Mon Sep 17 00:00:00 2001 From: jsg Date: Wed, 25 Mar 2026 23:20:35 +0000 Subject: [PATCH] drm: Fix use-after-free on framebuffers and property blobs when calling drm_dev_unplug From Maarten Lankhorst 074d06d3724ccab0c5bb779db594a82b6405e501 in linux-6.18.y/6.18.20 6bee098b91417654703e17eb5c1822c6dfd0c01d in mainline linux --- sys/dev/pci/drm/drm_file.c | 5 ++++- sys/dev/pci/drm/drm_mode_config.c | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/sys/dev/pci/drm/drm_file.c b/sys/dev/pci/drm/drm_file.c index 03fe6cf87ef..699dfdbc4c2 100644 --- a/sys/dev/pci/drm/drm_file.c +++ b/sys/dev/pci/drm/drm_file.c @@ -235,6 +235,7 @@ static void drm_events_release(struct drm_file *file_priv) void drm_file_free(struct drm_file *file) { struct drm_device *dev; + int idx; if (!file) return; @@ -257,9 +258,11 @@ void drm_file_free(struct drm_file *file) drm_events_release(file); - if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (drm_core_check_feature(dev, DRIVER_MODESET) && + drm_dev_enter(dev, &idx)) { drm_fb_release(file); drm_property_destroy_user_blobs(dev, file); + drm_dev_exit(idx); } if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) diff --git a/sys/dev/pci/drm/drm_mode_config.c b/sys/dev/pci/drm/drm_mode_config.c index 7ebff476a7e..c66c5dd09fd 100644 --- a/sys/dev/pci/drm/drm_mode_config.c +++ b/sys/dev/pci/drm/drm_mode_config.c @@ -570,10 +570,13 @@ void drm_mode_config_cleanup(struct drm_device *dev) */ WARN_ON(!list_empty(&dev->mode_config.fb_list)); list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { - struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]"); + if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) { + struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]"); - drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); - drm_framebuffer_print_info(&p, 1, fb); + drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); + drm_framebuffer_print_info(&p, 1, fb); + } + list_del_init(&fb->filp_head); drm_framebuffer_free(&fb->base.refcount); }