Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/gud: fix NULL fb and crtc dereferences on USB disconnect

On disconnect drm_atomic_helper_disable_all() is called which
sets both the fb and crtc for a plane to NULL before invoking a commit.

This causes a kernel oops on every display disconnect.

Add guards for those dereferences.

Cc: <stable@vger.kernel.org> # 6.18.x
Fixes: 73cfd166e045 ("drm/gud: Replace simple display pipe with DRM atomic helpers")
Signed-off-by: Shenghao Yang <me@shenghaoyang.info>
Reviewed-by: Ruben Wauters <rubenru09@aol.com>
Signed-off-by: Ruben Wauters <rubenru09@aol.com>
Link: https://patch.msgid.link/20251231055039.44266-1-me@shenghaoyang.info

authored by

Shenghao Yang and committed by
Ruben Wauters
dc2d5ddb 9380dc33

+8 -12
+8 -12
drivers/gpu/drm/gud/gud_pipe.c
··· 457 457 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); 458 458 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); 459 459 struct drm_crtc *crtc = new_plane_state->crtc; 460 - struct drm_crtc_state *crtc_state; 460 + struct drm_crtc_state *crtc_state = NULL; 461 461 const struct drm_display_mode *mode; 462 462 struct drm_framebuffer *old_fb = old_plane_state->fb; 463 463 struct drm_connector_state *connector_state = NULL; 464 464 struct drm_framebuffer *fb = new_plane_state->fb; 465 - const struct drm_format_info *format = fb->format; 465 + const struct drm_format_info *format; 466 466 struct drm_connector *connector; 467 467 unsigned int i, num_properties; 468 468 struct gud_state_req *req; 469 469 int idx, ret; 470 470 size_t len; 471 471 472 - if (drm_WARN_ON_ONCE(plane->dev, !fb)) 473 - return -EINVAL; 474 - 475 - if (drm_WARN_ON_ONCE(plane->dev, !crtc)) 476 - return -EINVAL; 477 - 478 - crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 479 - 480 - mode = &crtc_state->mode; 472 + if (crtc) 473 + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 481 474 482 475 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 483 476 DRM_PLANE_NO_SCALING, ··· 484 491 485 492 if (old_plane_state->rotation != new_plane_state->rotation) 486 493 crtc_state->mode_changed = true; 494 + 495 + mode = &crtc_state->mode; 496 + format = fb->format; 487 497 488 498 if (old_fb && old_fb->format != format) 489 499 crtc_state->mode_changed = true; ··· 594 598 struct drm_atomic_helper_damage_iter iter; 595 599 int ret, idx; 596 600 597 - if (crtc->state->mode_changed || !crtc->state->enable) { 601 + if (!crtc || crtc->state->mode_changed || !crtc->state->enable) { 598 602 cancel_work_sync(&gdrm->work); 599 603 mutex_lock(&gdrm->damage_lock); 600 604 if (gdrm->fb) {