diff options
| author | Manoj Rao <manojraj@codeaurora.org> | 2013-08-19 13:50:33 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:21:39 -0700 |
| commit | ad310ea9b17d96dd98121f1ada7d9fb41523aa85 (patch) | |
| tree | eb5d33afa69f244473638d3d4f60073414aa4bc8 | |
| parent | 618fb2ec3f30051fce9b90e2fa2c9bcb604eadd9 (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.c | 28 |
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__); } /* |
