drm/sysfs: Grab lock for edid/modes_show
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 2 Oct 2015 11:01:02 +0000 (13:01 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 24 Nov 2015 10:47:47 +0000 (11:47 +0100)
We chase pointers/lists without taking the locks protecting them,
which isn't that good.

Fix it.

v2: Actually unlock properly, spotted by Julia.

v3: Put the label _before_ the mutex_unlock (Emil)

Cc: Emil Velikov <emil.l.velikov@gmail.com>
Cc: Julia Lawall <julia.lawall@lip6.fr>
Link: http://patchwork.freedesktop.org/patch/msgid/1443783662-23066-1-git-send-email-daniel.vetter@ffwll.ch
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/drm_sysfs.c

index 615b7e667320184df169765862df055f36d7e0fd..c75f02297d01c4799aa360f758851ba0ca7adfec 100644 (file)
@@ -256,23 +256,29 @@ static ssize_t edid_show(struct file *filp, struct kobject *kobj,
        struct drm_connector *connector = to_drm_connector(connector_dev);
        unsigned char *edid;
        size_t size;
+       ssize_t ret = 0;
 
+       mutex_lock(&connector->dev->mode_config.mutex);
        if (!connector->edid_blob_ptr)
-               return 0;
+               goto unlock;
 
        edid = connector->edid_blob_ptr->data;
        size = connector->edid_blob_ptr->length;
        if (!edid)
-               return 0;
+               goto unlock;
 
        if (off >= size)
-               return 0;
+               goto unlock;
 
        if (off + count > size)
                count = size - off;
        memcpy(buf, edid + off, count);
 
-       return count;
+       ret = count;
+unlock:
+       mutex_unlock(&connector->dev->mode_config.mutex);
+
+       return ret;
 }
 
 static ssize_t modes_show(struct device *device,
@@ -283,10 +289,12 @@ static ssize_t modes_show(struct device *device,
        struct drm_display_mode *mode;
        int written = 0;
 
+       mutex_lock(&connector->dev->mode_config.mutex);
        list_for_each_entry(mode, &connector->modes, head) {
                written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",
                                    mode->name);
        }
+       mutex_unlock(&connector->dev->mode_config.mutex);
 
        return written;
 }