1
0
Fork 0

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: 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>
hifive-unleashed-5.1
Ville Syrjälä 2018-09-20 21:51:29 +03:00
parent f26e1de5ec
commit 480b8b3e42
7 changed files with 44 additions and 21 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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",

View File

@ -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.
@ -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)
@ -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.
@ -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) {
@ -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.
@ -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) {
@ -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.
@ -1163,7 +1176,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;
@ -1171,6 +1184,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))
@ -1178,6 +1194,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;
@ -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.
@ -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;

View File

@ -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);