Skip to content

Commit

Permalink
video/hdmi: Pass buffer size to infoframe unpack functions
Browse files Browse the repository at this point in the history
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: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180920185145.1912-3-ville.syrjala@linux.intel.com
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
  • Loading branch information
Ville Syrjälä committed Oct 1, 2018
1 parent f26e1de commit 480b8b3
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 21 deletions.
2 changes: 1 addition & 1 deletion drivers/media/i2c/adv7511.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/i2c/adv7604.c
Original file line number Diff line number Diff line change
Expand Up @@ -2418,7 +2418,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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/i2c/adv7842.c
Original file line number Diff line number Diff line change
Expand Up @@ -2563,7 +2563,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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/i2c/tc358743.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/media/i2c/tda1997x.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
51 changes: 37 additions & 14 deletions drivers/video/hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1005,8 +1005,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.
Expand All @@ -1016,11 +1017,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)
Expand Down Expand Up @@ -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
* @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.
Expand All @@ -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.
*/
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) {
Expand All @@ -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
* @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.
Expand All @@ -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.
*/
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) {
Expand Down Expand Up @@ -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
* @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.
Expand All @@ -1163,21 +1176,27 @@ 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;
int ret;
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))
return -EINVAL;

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;
Expand Down Expand Up @@ -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
* @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.
Expand All @@ -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.
*/
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;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/hdmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ union hdmi_infoframe {
ssize_t
hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size);
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);

Expand Down

0 comments on commit 480b8b3

Please sign in to comment.