Commit 480b8b3e authored by Ville Syrjälä's avatar Ville Syrjälä

video/hdmi: Pass buffer size to infoframe unpack functions

To make sure the infoframe unpack functions don't end up examining
stack garbage or oopsing, let's pass in the size of the buffer.

v2: Convert tda1997x.c as well (kbuild test robot)

Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: linux-media@vger.kernel.org
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180920185145.1912-3-ville.syrjala@linux.intel.comAcked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
parent f26e1de5
...@@ -550,7 +550,7 @@ static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_ ...@@ -550,7 +550,7 @@ static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_
buffer[3] = 0; buffer[3] = 0;
buffer[3] = hdmi_infoframe_checksum(buffer, len + 4); 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); v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
return; return;
} }
......
...@@ -2418,7 +2418,7 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index, ...@@ -2418,7 +2418,7 @@ static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
buffer[i + 3] = infoframe_read(sd, buffer[i + 3] = infoframe_read(sd,
adv76xx_cri[index].payload_addr + i); 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__, v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
adv76xx_cri[index].desc); adv76xx_cri[index].desc);
return -ENOENT; return -ENOENT;
......
...@@ -2563,7 +2563,7 @@ static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infofr ...@@ -2563,7 +2563,7 @@ static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infofr
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
buffer[i + 3] = infoframe_read(sd, cri->payload_addr + 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); v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
return; return;
} }
......
...@@ -444,7 +444,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd) ...@@ -444,7 +444,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd)
i2c_rd(sd, PK_AVI_0HEAD, buffer, HDMI_INFOFRAME_SIZE(AVI)); 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__); v4l2_err(sd, "%s: unpack of AVI infoframe failed\n", __func__);
return; return;
} }
......
...@@ -1253,7 +1253,7 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr) ...@@ -1253,7 +1253,7 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr)
/* read data */ /* read data */
len = io_readn(sd, addr, sizeof(buffer), buffer); len = io_readn(sd, addr, sizeof(buffer), buffer);
err = hdmi_infoframe_unpack(&frame, buffer); err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer));
if (err) { if (err) {
v4l_err(state->client, v4l_err(state->client,
"failed parsing %d byte infoframe: 0x%04x/0x%02x\n", "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) ...@@ -1928,7 +1928,7 @@ static int tda1997x_log_infoframe(struct v4l2_subdev *sd, int addr)
/* read data */ /* read data */
len = io_readn(sd, addr, sizeof(buffer), buffer); len = io_readn(sd, addr, sizeof(buffer), buffer);
v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len); 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) { if (err) {
v4l_err(state->client, v4l_err(state->client,
"failed parsing %d byte infoframe: 0x%04x/0x%02x\n", "failed parsing %d byte infoframe: 0x%04x/0x%02x\n",
......
...@@ -1005,8 +1005,9 @@ EXPORT_SYMBOL(hdmi_infoframe_log); ...@@ -1005,8 +1005,9 @@ EXPORT_SYMBOL(hdmi_infoframe_log);
/** /**
* hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe
* @buffer: source buffer
* @frame: HDMI AVI infoframe * @frame: HDMI AVI infoframe
* @buffer: source buffer
* @size: size of buffer
* *
* Unpacks the information contained in binary @buffer into a structured * Unpacks the information contained in binary @buffer into a structured
* @frame of the HDMI Auxiliary Video (AVI) information frame. * @frame of the HDMI Auxiliary Video (AVI) information frame.
...@@ -1016,11 +1017,14 @@ EXPORT_SYMBOL(hdmi_infoframe_log); ...@@ -1016,11 +1017,14 @@ EXPORT_SYMBOL(hdmi_infoframe_log);
* Returns 0 on success or a negative error code on failure. * Returns 0 on success or a negative error code on failure.
*/ */
static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
const void *buffer) const void *buffer, size_t size)
{ {
const u8 *ptr = buffer; const u8 *ptr = buffer;
int ret; int ret;
if (size < HDMI_INFOFRAME_SIZE(AVI))
return -EINVAL;
if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI || if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||
ptr[1] != 2 || ptr[1] != 2 ||
ptr[2] != HDMI_AVI_INFOFRAME_SIZE) ptr[2] != HDMI_AVI_INFOFRAME_SIZE)
...@@ -1068,8 +1072,9 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, ...@@ -1068,8 +1072,9 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
/** /**
* hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe
* @buffer: source buffer
* @frame: HDMI SPD infoframe * @frame: HDMI SPD infoframe
* @buffer: source buffer
* @size: size of buffer
* *
* Unpacks the information contained in binary @buffer into a structured * Unpacks the information contained in binary @buffer into a structured
* @frame of the HDMI Source Product Description (SPD) information frame. * @frame of the HDMI Source Product Description (SPD) information frame.
...@@ -1079,11 +1084,14 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, ...@@ -1079,11 +1084,14 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
* Returns 0 on success or a negative error code on failure. * Returns 0 on success or a negative error code on failure.
*/ */
static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
const void *buffer) const void *buffer, size_t size)
{ {
const u8 *ptr = buffer; const u8 *ptr = buffer;
int ret; int ret;
if (size < HDMI_INFOFRAME_SIZE(SPD))
return -EINVAL;
if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD || if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||
ptr[1] != 1 || ptr[1] != 1 ||
ptr[2] != HDMI_SPD_INFOFRAME_SIZE) { ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {
...@@ -1106,8 +1114,9 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, ...@@ -1106,8 +1114,9 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
/** /**
* hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe
* @buffer: source buffer
* @frame: HDMI Audio infoframe * @frame: HDMI Audio infoframe
* @buffer: source buffer
* @size: size of buffer
* *
* Unpacks the information contained in binary @buffer into a structured * Unpacks the information contained in binary @buffer into a structured
* @frame of the HDMI Audio information frame. * @frame of the HDMI Audio information frame.
...@@ -1117,11 +1126,14 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, ...@@ -1117,11 +1126,14 @@ static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
* Returns 0 on success or a negative error code on failure. * Returns 0 on success or a negative error code on failure.
*/ */
static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
const void *buffer) const void *buffer, size_t size)
{ {
const u8 *ptr = buffer; const u8 *ptr = buffer;
int ret; int ret;
if (size < HDMI_INFOFRAME_SIZE(AUDIO))
return -EINVAL;
if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO || if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||
ptr[1] != 1 || ptr[1] != 1 ||
ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) { ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {
...@@ -1151,8 +1163,9 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, ...@@ -1151,8 +1163,9 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
/** /**
* hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe
* @buffer: source buffer
* @frame: HDMI Vendor infoframe * @frame: HDMI Vendor infoframe
* @buffer: source buffer
* @size: size of buffer
* *
* Unpacks the information contained in binary @buffer into a structured * Unpacks the information contained in binary @buffer into a structured
* @frame of the HDMI Vendor information frame. * @frame of the HDMI Vendor information frame.
...@@ -1163,7 +1176,7 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, ...@@ -1163,7 +1176,7 @@ static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
*/ */
static int static int
hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
const void *buffer) const void *buffer, size_t size)
{ {
const u8 *ptr = buffer; const u8 *ptr = buffer;
size_t length; size_t length;
...@@ -1171,6 +1184,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, ...@@ -1171,6 +1184,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
u8 hdmi_video_format; u8 hdmi_video_format;
struct hdmi_vendor_infoframe *hvf = &frame->hdmi; struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
if (size < HDMI_INFOFRAME_HEADER_SIZE)
return -EINVAL;
if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR || if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
ptr[1] != 1 || ptr[1] != 1 ||
(ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6)) (ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6))
...@@ -1178,6 +1194,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, ...@@ -1178,6 +1194,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
length = ptr[2]; length = ptr[2];
if (size < HDMI_INFOFRAME_HEADER_SIZE + length)
return -EINVAL;
if (hdmi_infoframe_checksum(buffer, if (hdmi_infoframe_checksum(buffer,
HDMI_INFOFRAME_HEADER_SIZE + length) != 0) HDMI_INFOFRAME_HEADER_SIZE + length) != 0)
return -EINVAL; return -EINVAL;
...@@ -1224,8 +1243,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, ...@@ -1224,8 +1243,9 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
/** /**
* hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe
* @buffer: source buffer
* @frame: HDMI infoframe * @frame: HDMI infoframe
* @buffer: source buffer
* @size: size of buffer
* *
* Unpacks the information contained in binary buffer @buffer into a structured * Unpacks the information contained in binary buffer @buffer into a structured
* @frame of a HDMI infoframe. * @frame of a HDMI infoframe.
...@@ -1235,23 +1255,26 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, ...@@ -1235,23 +1255,26 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
* Returns 0 on success or a negative error code on failure. * Returns 0 on success or a negative error code on failure.
*/ */
int hdmi_infoframe_unpack(union hdmi_infoframe *frame, int hdmi_infoframe_unpack(union hdmi_infoframe *frame,
const void *buffer) const void *buffer, size_t size)
{ {
int ret; int ret;
const u8 *ptr = buffer; const u8 *ptr = buffer;
if (size < HDMI_INFOFRAME_HEADER_SIZE)
return -EINVAL;
switch (ptr[0]) { switch (ptr[0]) {
case HDMI_INFOFRAME_TYPE_AVI: case HDMI_INFOFRAME_TYPE_AVI:
ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer); ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size);
break; break;
case HDMI_INFOFRAME_TYPE_SPD: case HDMI_INFOFRAME_TYPE_SPD:
ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer); ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size);
break; break;
case HDMI_INFOFRAME_TYPE_AUDIO: case HDMI_INFOFRAME_TYPE_AUDIO:
ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer); ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer, size);
break; break;
case HDMI_INFOFRAME_TYPE_VENDOR: 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; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
......
...@@ -333,7 +333,7 @@ union hdmi_infoframe { ...@@ -333,7 +333,7 @@ union hdmi_infoframe {
ssize_t ssize_t
hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size); hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size);
int hdmi_infoframe_unpack(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, void hdmi_infoframe_log(const char *level, struct device *dev,
union hdmi_infoframe *frame); union hdmi_infoframe *frame);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment