OSDN Git Service

drm/fb-helper: fix segfaults in drm_fb_helper_debug_*
authorStefan Christ <contact@stefanchrist.eu>
Sun, 13 Nov 2016 23:03:11 +0000 (00:03 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 14 Nov 2016 06:47:34 +0000 (07:47 +0100)
A drm driver that is implementing

      fb_debug_enter and fb_debug_leave

in struct fb_ops with drm fb helper functions

     drm_fb_helper_debug_enter and drm_fb_helper_debug_leave

must also implement the callback 'mode_set_base_atomic' in struct
drm_crtc_helper_funcs. See Documentation/DocBook/kgdb.tmpl.  The current
implementation will segfault when 'mode_set_base_atomic' is a NULL
pointer.

Before this patch at least the drm drivers armada, ast, qxl, udl and
virtio do not have a 'mode_set_base_atomic' implementation but using
drm_fb_helper_debug_(enter|leave). So these drivers may segfault when
callbacks fb_debug_(enter|leave) are called.

Avoid the issue by just checking for NULL pointers. So all drivers can
unconditionally implement fb_debug_(enter|leave) with the drm_fb_helper
functions. If callback 'mode_set_base_atomic' is not implemented, the
code in drm_fb_helper_debug_(enter|leave) does effectively nothing.

Signed-off-by: Stefan Christ <contact@stefanchrist.eu>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1479078208-25221-2-git-send-email-contact@stefanchrist.eu
drivers/gpu/drm/drm_fb_helper.c

index 36797c4..1454781 100644 (file)
@@ -256,6 +256,9 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
                                continue;
 
                        funcs = mode_set->crtc->helper_private;
+                       if (funcs->mode_set_base_atomic == NULL)
+                               continue;
+
                        drm_fb_helper_save_lut_atomic(mode_set->crtc, helper);
                        funcs->mode_set_base_atomic(mode_set->crtc,
                                                    mode_set->fb,
@@ -309,6 +312,9 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
                        continue;
                }
 
+               if (funcs->mode_set_base_atomic == NULL)
+                       continue;
+
                drm_fb_helper_restore_lut_atomic(mode_set->crtc);
                funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
                                            crtc->y, LEAVE_ATOMIC_MODE_SET);