diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2012-08-16 10:55:05 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-09-12 21:22:30 -0400 |
commit | 8504072a2a47c80344c1cf81537d1d433a979fc6 (patch) | |
tree | 779f70248093e5cb09145544bcc79f423aadc5bb /drivers | |
parent | 9e50b9d55e9c38440175a0f27f77708e2270b140 (diff) |
drm: edid: Add bounds checking to HDMI VSDB parsing
The length of HDMI VSDB must be at least 5 bytes. Other than the minimum,
nothing else about the length is specified. Check the length before
accessing any additional field beyond the minimum length.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7f392534abcc..eadaf4800f46 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -1576,19 +1576,28 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid) | |||
1576 | } | 1576 | } |
1577 | 1577 | ||
1578 | static void | 1578 | static void |
1579 | parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db) | 1579 | parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db) |
1580 | { | 1580 | { |
1581 | connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */ | 1581 | u8 len = cea_db_payload_len(db); |
1582 | 1582 | ||
1583 | connector->dvi_dual = db[6] & 1; | 1583 | if (len >= 6) { |
1584 | connector->max_tmds_clock = db[7] * 5; | 1584 | connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */ |
1585 | 1585 | connector->dvi_dual = db[6] & 1; | |
1586 | connector->latency_present[0] = db[8] >> 7; | 1586 | } |
1587 | connector->latency_present[1] = (db[8] >> 6) & 1; | 1587 | if (len >= 7) |
1588 | connector->video_latency[0] = db[9]; | 1588 | connector->max_tmds_clock = db[7] * 5; |
1589 | connector->audio_latency[0] = db[10]; | 1589 | if (len >= 8) { |
1590 | connector->video_latency[1] = db[11]; | 1590 | connector->latency_present[0] = db[8] >> 7; |
1591 | connector->audio_latency[1] = db[12]; | 1591 | connector->latency_present[1] = (db[8] >> 6) & 1; |
1592 | } | ||
1593 | if (len >= 9) | ||
1594 | connector->video_latency[0] = db[9]; | ||
1595 | if (len >= 10) | ||
1596 | connector->audio_latency[0] = db[10]; | ||
1597 | if (len >= 11) | ||
1598 | connector->video_latency[1] = db[11]; | ||
1599 | if (len >= 12) | ||
1600 | connector->audio_latency[1] = db[12]; | ||
1592 | 1601 | ||
1593 | DRM_LOG_KMS("HDMI: DVI dual %d, " | 1602 | DRM_LOG_KMS("HDMI: DVI dual %d, " |
1594 | "max TMDS clock %d, " | 1603 | "max TMDS clock %d, " |
@@ -1684,7 +1693,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) | |||
1684 | break; | 1693 | break; |
1685 | case VENDOR_BLOCK: | 1694 | case VENDOR_BLOCK: |
1686 | /* HDMI Vendor-Specific Data Block */ | 1695 | /* HDMI Vendor-Specific Data Block */ |
1687 | if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0) | 1696 | if (dbl >= 5 && db[1] == 0x03 && db[2] == 0x0c && db[3] == 0) |
1688 | parse_hdmi_vsdb(connector, db); | 1697 | parse_hdmi_vsdb(connector, db); |
1689 | break; | 1698 | break; |
1690 | default: | 1699 | default: |