diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-06-20 16:28:37 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-06-21 03:18:44 -0400 |
commit | e94ac3510b6a0f696f2c442c4fc4051c8101ef12 (patch) | |
tree | 88fa50e33f18b7fd526da4eff6cebcda34c67b01 | |
parent | 0f933328f018c118ded2035f12068bbdfdef399d (diff) |
drm: Fix GETCONNECTOR regression
In
commit 91eefc05f0ac71902906b2058360e61bd25137fe
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: 91eefc05f0ac ("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: "H.J. Lu" <hjl.tools@gmail.com>
Tested-by: "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: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170620202837.1701-1-daniel.vetter@ffwll.ch
-rw-r--r-- | drivers/gpu/drm/drm_connector.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 9f847615ac74..48ca2457df8c 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c | |||
@@ -1229,21 +1229,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1229 | if (!connector) | 1229 | if (!connector) |
1230 | return -ENOENT; | 1230 | return -ENOENT; |
1231 | 1231 | ||
1232 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | ||
1233 | encoder = drm_connector_get_encoder(connector); | ||
1234 | if (encoder) | ||
1235 | out_resp->encoder_id = encoder->base.id; | ||
1236 | else | ||
1237 | out_resp->encoder_id = 0; | ||
1238 | |||
1239 | ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic, | ||
1240 | (uint32_t __user *)(unsigned long)(out_resp->props_ptr), | ||
1241 | (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), | ||
1242 | &out_resp->count_props); | ||
1243 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
1244 | if (ret) | ||
1245 | goto out_unref; | ||
1246 | |||
1247 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) | 1232 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) |
1248 | if (connector->encoder_ids[i] != 0) | 1233 | if (connector->encoder_ids[i] != 0) |
1249 | encoders_count++; | 1234 | encoders_count++; |
@@ -1256,7 +1241,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1256 | if (put_user(connector->encoder_ids[i], | 1241 | if (put_user(connector->encoder_ids[i], |
1257 | encoder_ptr + copied)) { | 1242 | encoder_ptr + copied)) { |
1258 | ret = -EFAULT; | 1243 | ret = -EFAULT; |
1259 | goto out_unref; | 1244 | goto out; |
1260 | } | 1245 | } |
1261 | copied++; | 1246 | copied++; |
1262 | } | 1247 | } |
@@ -1300,15 +1285,32 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
1300 | if (copy_to_user(mode_ptr + copied, | 1285 | if (copy_to_user(mode_ptr + copied, |
1301 | &u_mode, sizeof(u_mode))) { | 1286 | &u_mode, sizeof(u_mode))) { |
1302 | ret = -EFAULT; | 1287 | ret = -EFAULT; |
1288 | mutex_unlock(&dev->mode_config.mutex); | ||
1289 | |||
1303 | goto out; | 1290 | goto out; |
1304 | } | 1291 | } |
1305 | copied++; | 1292 | copied++; |
1306 | } | 1293 | } |
1307 | } | 1294 | } |
1308 | out_resp->count_modes = mode_count; | 1295 | out_resp->count_modes = mode_count; |
1309 | out: | ||
1310 | mutex_unlock(&dev->mode_config.mutex); | 1296 | mutex_unlock(&dev->mode_config.mutex); |
1311 | out_unref: | 1297 | |
1298 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | ||
1299 | encoder = drm_connector_get_encoder(connector); | ||
1300 | if (encoder) | ||
1301 | out_resp->encoder_id = encoder->base.id; | ||
1302 | else | ||
1303 | out_resp->encoder_id = 0; | ||
1304 | |||
1305 | /* Only grab properties after probing, to make sure EDID and other | ||
1306 | * properties reflect the latest status. */ | ||
1307 | ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic, | ||
1308 | (uint32_t __user *)(unsigned long)(out_resp->props_ptr), | ||
1309 | (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), | ||
1310 | &out_resp->count_props); | ||
1311 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
1312 | |||
1313 | out: | ||
1312 | drm_connector_put(connector); | 1314 | drm_connector_put(connector); |
1313 | 1315 | ||
1314 | return ret; | 1316 | return ret; |