drm/core: Fix ordering in drm_mode_config_cleanup.
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Tue, 22 Mar 2016 14:42:14 +0000 (15:42 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 12 Apr 2016 10:43:26 +0000 (12:43 +0200)
__drm_atomic_helper_plane_destroy_state calls
drm_framebuffer_unreference, which means that if drm_framebuffer_free
is called before plane->destroy freed memory will be accessed.

A similar case happens for the blob list, which was freed before the
crtc state was, resulting in the unreference_blob from crtc_destroy_state
pointing to garbage memory causing another opportunity for a GPF.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1458657734-21866-1-git-send-email-maarten.lankhorst@linux.intel.com
drivers/gpu/drm/drm_crtc.c

index 55ffde5a3a4a666ac6f13516907cca56c7104355..f7fe9e153dec68a3494335fb7e1630cbe9106b49 100644 (file)
@@ -5914,6 +5914,15 @@ void drm_mode_config_cleanup(struct drm_device *dev)
                drm_property_destroy(dev, property);
        }
 
+       list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
+                                head) {
+               plane->funcs->destroy(plane);
+       }
+
+       list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
+               crtc->funcs->destroy(crtc);
+       }
+
        list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
                                 head_global) {
                drm_property_unreference_blob(blob);
@@ -5932,15 +5941,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
                drm_framebuffer_free(&fb->refcount);
        }
 
-       list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
-                                head) {
-               plane->funcs->destroy(plane);
-       }
-
-       list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
-               crtc->funcs->destroy(crtc);
-       }
-
        ida_destroy(&dev->mode_config.connector_ida);
        idr_destroy(&dev->mode_config.tile_idr);
        idr_destroy(&dev->mode_config.crtc_idr);