Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e94ac351 authored by Daniel Vetter's avatar Daniel Vetter
Browse files

drm: Fix GETCONNECTOR regression



In

commit 91eefc05
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Wed Dec 14 00:08:10 2016 +0100

    drm: Tighten locking in drm_mode_getconnector

I reordered the logic a bit in that IOCTL, but that broke userspace
since it'll get the new mode list, but not the new property values.
Fix that again.

v2: Fix up the error path handling when copy_to_user for the modes
failes (Dhinakaran).

Fixes: 91eefc05 ("drm: Tighten locking in drm_mode_getconnector")
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel@lists.freedesktop.org
Reported-by: default avatar"H.J. Lu" <hjl.tools@gmail.com>
Tested-by: default avatar"H.J. Lu" <hjl.tools@gmail.com>
Cc: <stable@vger.kernel.org> # v4.11+
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100576


Cc: "H.J. Lu" <hjl.tools@gmail.com>
Cc: "Pandiyan, Dhinakaran" <dhinakaran.pandiyan@intel.com>
Reviewed-by: default avatarSean Paul <seanpaul@chromium.org>
Reviewed-by: default avatarDhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170620202837.1701-1-daniel.vetter@ffwll.ch
parent 0f933328
Loading
Loading
Loading
Loading
+20 −18
Original line number Diff line number Diff line
@@ -1229,21 +1229,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
	if (!connector)
		return -ENOENT;

	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
	encoder = drm_connector_get_encoder(connector);
	if (encoder)
		out_resp->encoder_id = encoder->base.id;
	else
		out_resp->encoder_id = 0;

	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
			(uint32_t __user *)(unsigned long)(out_resp->props_ptr),
			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
			&out_resp->count_props);
	drm_modeset_unlock(&dev->mode_config.connection_mutex);
	if (ret)
		goto out_unref;

	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
		if (connector->encoder_ids[i] != 0)
			encoders_count++;
@@ -1256,7 +1241,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
				if (put_user(connector->encoder_ids[i],
					     encoder_ptr + copied)) {
					ret = -EFAULT;
					goto out_unref;
					goto out;
				}
				copied++;
			}
@@ -1300,15 +1285,32 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
			if (copy_to_user(mode_ptr + copied,
					 &u_mode, sizeof(u_mode))) {
				ret = -EFAULT;
				mutex_unlock(&dev->mode_config.mutex);

				goto out;
			}
			copied++;
		}
	}
	out_resp->count_modes = mode_count;
out:
	mutex_unlock(&dev->mode_config.mutex);
out_unref:

	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
	encoder = drm_connector_get_encoder(connector);
	if (encoder)
		out_resp->encoder_id = encoder->base.id;
	else
		out_resp->encoder_id = 0;

	/* Only grab properties after probing, to make sure EDID and other
	 * properties reflect the latest status. */
	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
			(uint32_t __user *)(unsigned long)(out_resp->props_ptr),
			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
			&out_resp->count_props);
	drm_modeset_unlock(&dev->mode_config.connection_mutex);

out:
	drm_connector_put(connector);

	return ret;