diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 88349b5053cc..cec5ebb1c9e6 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -550,7 +550,7 @@ static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_ buffer[3] = 0; buffer[3] = hdmi_infoframe_checksum(buffer, len + 4); - if (hdmi_infoframe_unpack(&frame, buffer) < 0) { + if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) { v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc); return; } diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f01964c36ad5..1a2c7d6fdfe0 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2420,7 +2420,7 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index, buffer[i + 3] = infoframe_read(sd, adv76xx_cri[index].payload_addr + i); - if (hdmi_infoframe_unpack(frame, buffer) < 0) { + if (hdmi_infoframe_unpack(frame, buffer, sizeof(buffer)) < 0) { v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, adv76xx_cri[index].desc); return -ENOENT; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index bb43a75ed6d0..b74035679bf7 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -2565,7 +2565,7 @@ static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infofr for (i = 0; i < len; i++) buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i); - if (hdmi_infoframe_unpack(&frame, buffer) < 0) { + if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) { v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc); return; } diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 26070fb6ce4e..f0fbaa3b5e06 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -444,7 +444,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd) i2c_rd(sd, PK_AVI_0HEAD, buffer, HDMI_INFOFRAME_SIZE(AVI)); - if (hdmi_infoframe_unpack(&frame, buffer) < 0) { + if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) { v4l2_err(sd, "%s: unpack of AVI infoframe failed\n", __func__); return; } diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index d114ac5243ec..195a1fc74ee8 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -1253,7 +1253,7 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr) /* read data */ len = io_readn(sd, addr, sizeof(buffer), buffer); - err = hdmi_infoframe_unpack(&frame, buffer); + err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); if (err) { v4l_err(state->client, "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", @@ -1928,7 +1928,7 @@ static int tda1997x_log_infoframe(struct v4l2_subdev *sd, int addr) /* read data */ len = io_readn(sd, addr, sizeof(buffer), buffer); v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len); - err = hdmi_infoframe_unpack(&frame, buffer); + err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); if (err) { v4l_err(state->client, "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index fd0091d75f34..00e8409ed88c 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -1568,8 +1568,9 @@ EXPORT_SYMBOL(hdmi_infoframe_log); /** * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe - * @buffer: source buffer * @frame: HDMI AVI infoframe + * @buffer: source buffer + * @size: size of buffer * * Unpacks the information contained in binary @buffer into a structured * @frame of the HDMI Auxiliary Video (AVI) information frame. @@ -1579,11 +1580,14 @@ EXPORT_SYMBOL(hdmi_infoframe_log); * Returns 0 on success or a negative error code on failure. */ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, - const void *buffer) + const void *buffer, size_t size) { const u8 *ptr = buffer; int ret; + if (size < HDMI_INFOFRAME_SIZE(AVI)) + return -EINVAL; + if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI || ptr[1] != 2 || ptr[2] != HDMI_AVI_INFOFRAME_SIZE) @@ -1631,8 +1635,9 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, /** * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe - * @buffer: source buffer * @frame: HDMI SPD infoframe + * @buffer: source buffer + * @size: size of buffer * * Unpacks the information contained in binary @buffer into a structured * @frame of the HDMI Source Product Description (SPD) information frame. @@ -1642,11 +1647,14 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, * Returns 0 on success or a negative error code on failure. */ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, - const void *buffer) + const void *buffer, size_t size) { const u8 *ptr = buffer; int ret; + if (size < HDMI_INFOFRAME_SIZE(SPD)) + return -EINVAL; + if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD || ptr[1] != 1 || ptr[2] != HDMI_SPD_INFOFRAME_SIZE) { @@ -1669,8 +1677,9 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, /** * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe - * @buffer: source buffer * @frame: HDMI Audio infoframe + * @buffer: source buffer + * @size: size of buffer * * Unpacks the information contained in binary @buffer into a structured * @frame of the HDMI Audio information frame. @@ -1680,11 +1689,14 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, * Returns 0 on success or a negative error code on failure. */ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, - const void *buffer) + const void *buffer, size_t size) { const u8 *ptr = buffer; int ret; + if (size < HDMI_INFOFRAME_SIZE(AUDIO)) + return -EINVAL; + if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO || ptr[1] != 1 || ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) { @@ -1714,8 +1726,9 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, /** * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe - * @buffer: source buffer * @frame: HDMI Vendor infoframe + * @buffer: source buffer + * @size: size of buffer * * Unpacks the information contained in binary @buffer into a structured * @frame of the HDMI Vendor information frame. @@ -1726,7 +1739,7 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, */ static int hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, - const void *buffer) + const void *buffer, size_t size) { const u8 *ptr = buffer; size_t length; @@ -1734,6 +1747,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, u8 hdmi_video_format; struct hdmi_vendor_infoframe *hvf = &frame->hdmi; + if (size < HDMI_INFOFRAME_HEADER_SIZE) + return -EINVAL; + if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR || ptr[1] != 1 || (ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6)) @@ -1741,6 +1757,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, length = ptr[2]; + if (size < HDMI_INFOFRAME_HEADER_SIZE + length) + return -EINVAL; + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_HEADER_SIZE + length) != 0) return -EINVAL; @@ -1787,8 +1806,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, /** * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe - * @buffer: source buffer * @frame: HDMI infoframe + * @buffer: source buffer + * @size: size of buffer * * Unpacks the information contained in binary buffer @buffer into a structured * @frame of a HDMI infoframe. @@ -1798,23 +1818,26 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, * Returns 0 on success or a negative error code on failure. */ int hdmi_infoframe_unpack(union hdmi_infoframe *frame, - const void *buffer) + const void *buffer, size_t size) { int ret; const u8 *ptr = buffer; + if (size < HDMI_INFOFRAME_HEADER_SIZE) + return -EINVAL; + switch (ptr[0]) { case HDMI_INFOFRAME_TYPE_AVI: - ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer); + ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size); break; case HDMI_INFOFRAME_TYPE_SPD: - ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer); + ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size); break; case HDMI_INFOFRAME_TYPE_AUDIO: - ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer); + ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer, size); break; case HDMI_INFOFRAME_TYPE_VENDOR: - ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer); + ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer, size); break; default: ret = -EINVAL; diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index ceb258593f28..8b8b5d5224ce 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -403,7 +403,7 @@ ssize_t hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, void *buffer, size_t size); int hdmi_infoframe_check(union hdmi_infoframe *frame); int hdmi_infoframe_unpack(union hdmi_infoframe *frame, - const void *buffer); + const void *buffer, size_t size); void hdmi_infoframe_log(const char *level, struct device *dev, union hdmi_infoframe *frame);