summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoj Rao <manojraj@codeaurora.org>2013-08-19 13:50:33 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:21:39 -0700
commitad310ea9b17d96dd98121f1ada7d9fb41523aa85 (patch)
treeeb5d33afa69f244473638d3d4f60073414aa4bc8
parent618fb2ec3f30051fce9b90e2fa2c9bcb604eadd9 (diff)
msm: mdss: hdmi: bounds check for 3d data in vsd buf
Ensure the 3D formats are only read from the proper buffer region for vendor specific data block. This prevents illegal data being read from the EDID data. Change-Id: I36286db54241246aaa06c399e4b6e962d54d716d CRs-Fixed: 522147 Signed-off-by: Manoj Rao <manojraj@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
index 24bdc082073d..c39d41d0bf34 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
@@ -887,7 +887,7 @@ static void hdmi_edid_add_sink_video_format(
}
} /* hdmi_edid_add_sink_video_format */
-static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
+static int hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
struct hdmi_edid_sink_data *sink_data, u32 num_of_cea_blocks)
{
u8 len, offset, present_multi_3d, hdmi_vic_len;
@@ -898,22 +898,34 @@ static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
3, &len) : NULL;
int i;
+ if (!vsd)
+ return -ENXIO;
+
offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
+ if (offset >= len - 1)
+ return -ETOOSMALL;
+
present_multi_3d = (vsd[offset] & 0x60) >> 5;
offset += 1;
+
hdmi_vic_len = (vsd[offset] >> 5) & 0x7;
hdmi_3d_len = vsd[offset] & 0x1F;
DEV_DBG("%s: EDID[3D]: HDMI_VIC_LEN = %d, HDMI_3D_LEN = %d\n", __func__,
hdmi_vic_len, hdmi_3d_len);
offset += (hdmi_vic_len + 1);
+ if (offset >= len - 1)
+ return -ETOOSMALL;
+
if (present_multi_3d == 1 || present_multi_3d == 2) {
DEV_DBG("%s: EDID[3D]: multi 3D present (%d)\n", __func__,
present_multi_3d);
/* 3d_structure_all */
structure_all = (vsd[offset] << 8) | vsd[offset + 1];
offset += 2;
+ if (offset >= len - 1)
+ return -ETOOSMALL;
hdmi_3d_len -= 2;
if (present_multi_3d == 2) {
/* 3d_structure_mask */
@@ -960,16 +972,18 @@ static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
i = 0;
while (hdmi_3d_len > 0) {
+ if (offset >= len - 1)
+ return -ETOOSMALL;
DEV_DBG("%s: EDID: 3D_Structure_%d @ 0x%x: %02x\n",
__func__, i + 1, offset, vsd[offset]);
-
if ((vsd[offset] >> 4) >=
sink_data->disp_multi_3d_mode_list_cnt) {
if ((vsd[offset] & 0x0F) >= 8) {
offset += 1;
hdmi_3d_len -= 1;
DEV_DBG("%s:EDID:3D_Detail_%d @ 0x%x: %02x\n",
- __func__, i + 1, offset, vsd[offset]);
+ __func__, i + 1, offset,
+ vsd[min_t(u32, offset, (len - 1))]);
}
i += 1;
offset += 1;
@@ -1005,12 +1019,13 @@ static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
hdmi_3d_len -= 1;
DEV_DBG("%s: EDID[3D]: 3D_Detail_%d @ 0x%x: %02x\n",
__func__, i + 1, offset,
- vsd[offset]);
+ vsd[min_t(u32, offset, (len - 1))]);
}
i += 1;
offset += 1;
hdmi_3d_len -= 1;
}
+ return 0;
} /* hdmi_edid_get_display_vsd_3d_mode */
static void hdmi_edid_get_extended_video_formats(
@@ -1063,6 +1078,7 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl,
u32 video_format = HDMI_VFRMT_640x480p60_4_3;
u32 has480p = false;
u8 len;
+ int rc;
const u8 *edid_blk0 = NULL;
const u8 *edid_blk1 = NULL;
const u8 *svd = NULL;
@@ -1313,8 +1329,10 @@ static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl,
}
/* 3d format described in Vendor Specific Data */
- hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
+ rc = hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
num_of_cea_blocks);
+ if (!rc)
+ pr_debug("%s: 3D formats in VSD\n", __func__);
}
/*