disp: msm: dp: validate edid before dereferencing
Currently, when using custom edid from debugfs, the
extensions data inside the edid block is not validated
before dereferencing the extension block.
The fix adds a edid validation function to validate
any custom edids before accessing any members in the
edid block.
Change-Id: I65e596cd6743febd5d55d968908619ebd50bef29
Signed-off-by: osaisruj <osaisruj@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 386c56c..97de1b8 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -165,7 +165,7 @@
kfree(buf);
if (!debug->dp_debug.sim_mode)
- debug->panel->set_edid(debug->panel, edid);
+ debug->panel->set_edid(debug->panel, edid, debug->edid_size);
mutex_unlock(&debug->lock);
return rc;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 7e6c44a..4b006c5 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -16,6 +16,7 @@
#include "msm_kms.h"
#include "dp_panel.h"
+#include <drm/drm_edid.h>
#define DP_PANEL_DEFAULT_BPP 24
#define DP_MAX_DS_PORT_COUNT 1
@@ -235,8 +236,24 @@
return 0;
}
+static int dp_panel_validate_edid(struct edid *edid, size_t edid_size)
+{
+ if (!edid || (edid_size < EDID_LENGTH))
+ return false;
-static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid)
+ if (EDID_LENGTH * (edid->extensions + 1) > edid_size) {
+ pr_err("edid size does not match allocated.\n");
+ return false;
+ }
+ if (!drm_edid_is_valid(edid)) {
+ pr_err("invalid edid.\n");
+ return false;
+ }
+ return true;
+}
+
+static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid,
+ size_t edid_size)
{
struct dp_panel_private *panel;
@@ -247,7 +264,7 @@
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
- if (edid) {
+ if (edid && dp_panel_validate_edid((struct edid *)edid, edid_size)) {
dp_panel->edid_ctrl->edid = (struct edid *)edid;
panel->custom_edid = true;
} else {
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 1a87a96..2c4622b 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -91,7 +91,7 @@
int (*get_modes)(struct dp_panel *dp_panel,
struct drm_connector *connector, struct dp_display_mode *mode);
void (*handle_sink_request)(struct dp_panel *dp_panel);
- int (*set_edid)(struct dp_panel *dp_panel, u8 *edid);
+ int (*set_edid)(struct dp_panel *dp_panel, u8 *edid, size_t edid_size);
int (*set_dpcd)(struct dp_panel *dp_panel, u8 *dpcd);
int (*setup_hdr)(struct dp_panel *dp_panel,
struct drm_msm_ext_hdr_metadata *hdr_meta);