Unverified Commit dc2d5ddb authored by Shenghao Yang's avatar Shenghao Yang Committed by Ruben Wauters
Browse files

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: 73cfd166 ("drm/gud: Replace simple display pipe with DRM atomic helpers")
Signed-off-by: default avatarShenghao Yang <me@shenghaoyang.info>
Reviewed-by: default avatarRuben Wauters <rubenru09@aol.com>
Signed-off-by: default avatarRuben Wauters <rubenru09@aol.com>
Link: https://patch.msgid.link/20251231055039.44266-1-me@shenghaoyang.info
parent 9380dc33
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -457,28 +457,21 @@ int gud_plane_atomic_check(struct drm_plane *plane,
	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
	struct drm_crtc *crtc = new_plane_state->crtc;
	struct drm_crtc_state *crtc_state;
	struct drm_crtc_state *crtc_state = NULL;
	const struct drm_display_mode *mode;
	struct drm_framebuffer *old_fb = old_plane_state->fb;
	struct drm_connector_state *connector_state = NULL;
	struct drm_framebuffer *fb = new_plane_state->fb;
	const struct drm_format_info *format = fb->format;
	const struct drm_format_info *format;
	struct drm_connector *connector;
	unsigned int i, num_properties;
	struct gud_state_req *req;
	int idx, ret;
	size_t len;

	if (drm_WARN_ON_ONCE(plane->dev, !fb))
		return -EINVAL;

	if (drm_WARN_ON_ONCE(plane->dev, !crtc))
		return -EINVAL;

	if (crtc)
		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);

	mode = &crtc_state->mode;

	ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
						  DRM_PLANE_NO_SCALING,
						  DRM_PLANE_NO_SCALING,
@@ -492,6 +485,9 @@ int gud_plane_atomic_check(struct drm_plane *plane,
	if (old_plane_state->rotation != new_plane_state->rotation)
		crtc_state->mode_changed = true;

	mode = &crtc_state->mode;
	format = fb->format;

	if (old_fb && old_fb->format != format)
		crtc_state->mode_changed = true;

@@ -598,7 +594,7 @@ void gud_plane_atomic_update(struct drm_plane *plane,
	struct drm_atomic_helper_damage_iter iter;
	int ret, idx;

	if (crtc->state->mode_changed || !crtc->state->enable) {
	if (!crtc || crtc->state->mode_changed || !crtc->state->enable) {
		cancel_work_sync(&gdrm->work);
		mutex_lock(&gdrm->damage_lock);
		if (gdrm->fb) {