drm/exynos/hdmi: Fix unsafe list iteration
authorMaciej Purski <m.purski@samsung.com>
Tue, 5 Sep 2017 12:23:02 +0000 (14:23 +0200)
committerInki Dae <inki.dae@samsung.com>
Wed, 20 Sep 2017 03:05:23 +0000 (12:05 +0900)
Function hdmi_mode_fixup() used bare list_for_each entry, which was
unsafe and caused memory corruption detected by kasan.
It now uses drm_for_each_connector_iter macro, which is now recommended
by the documentation and safe.

Signed-off-by: Maciej Purski <m.purski@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_hdmi.c

index 214fa5e51963898ee5288f98d536681cdbebdcd6..0109ff40b1db2a95da6997e982fe0adaf4496196 100644 (file)
@@ -944,22 +944,27 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder,
        struct drm_device *dev = encoder->dev;
        struct drm_connector *connector;
        struct drm_display_mode *m;
+       struct drm_connector_list_iter conn_iter;
        int mode_ok;
 
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &conn_iter);
+       drm_for_each_connector_iter(connector, &conn_iter) {
                if (connector->encoder == encoder)
                        break;
        }
+       if (connector)
+               drm_connector_get(connector);
+       drm_connector_list_iter_end(&conn_iter);
 
-       if (connector->encoder != encoder)
+       if (!connector)
                return true;
 
        mode_ok = hdmi_mode_valid(connector, adjusted_mode);
 
        if (mode_ok == MODE_OK)
-               return true;
+               goto cleanup;
 
        /*
         * Find the most suitable mode and copy it to adjusted_mode.
@@ -979,6 +984,9 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder,
                }
        }
 
+cleanup:
+       drm_connector_put(connector);
+
        return true;
 }