summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorAlyssa Milburn <amilburn@zall.org>2017-04-01 17:34:49 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-25 13:44:42 (GMT)
commit40616929f87e1bb236f5daa0dffa3a95553ac76a (patch)
treeab79d6cb541a249d15263f9231a54593a40b7b86 /drivers/media
parente42a6715d26bc777b545018d585333ee91cdbbe9 (diff)
downloadlinux-40616929f87e1bb236f5daa0dffa3a95553ac76a.tar.xz
dw2102: limit messages to buffer size
commit 950e252cb469f323740d78e4907843acef89eedb upstream. Otherwise the i2c transfer functions can read or write beyond the end of stack or heap buffers. Signed-off-by: Alyssa Milburn <amilburn@zall.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/usb/dvb-usb/dw2102.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index c3e6734..4a0cc54 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -205,6 +205,20 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
switch (num) {
case 2:
+ if (msg[0].len != 1) {
+ warn("i2c rd: len=%d is not 1!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
+ if (2 + msg[1].len > sizeof(buf6)) {
+ warn("i2c rd: len=%d is too big!\n",
+ msg[1].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
/* read si2109 register by number */
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
@@ -220,6 +234,13 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
case 1:
switch (msg[0].addr) {
case 0x68:
+ if (2 + msg[0].len > sizeof(buf6)) {
+ warn("i2c wr: len=%d is too big!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
/* write to si2109 register */
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
@@ -263,6 +284,13 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
/* first write first register number */
u8 ibuf[MAX_XFER_SIZE], obuf[3];
+ if (2 + msg[0].len != sizeof(obuf)) {
+ warn("i2c rd: len=%d is not 1!\n",
+ msg[0].len);
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
+
if (2 + msg[1].len > sizeof(ibuf)) {
warn("i2c rd: len=%d is too big!\n",
msg[1].len);
@@ -463,6 +491,12 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
/* first write first register number */
u8 ibuf[MAX_XFER_SIZE], obuf[3];
+ if (2 + msg[0].len != sizeof(obuf)) {
+ warn("i2c rd: len=%d is not 1!\n",
+ msg[0].len);
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
if (2 + msg[1].len > sizeof(ibuf)) {
warn("i2c rd: len=%d is too big!\n",
msg[1].len);
@@ -697,6 +731,13 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
msg[0].buf[0] = state->data[1];
break;
default:
+ if (3 + msg[0].len > sizeof(state->data)) {
+ warn("i2c wr: len=%d is too big!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
/* always i2c write*/
state->data[0] = 0x08;
state->data[1] = msg[0].addr;
@@ -712,6 +753,19 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
break;
case 2:
/* always i2c read */
+ if (4 + msg[0].len > sizeof(state->data)) {
+ warn("i2c rd: len=%d is too big!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+ if (1 + msg[1].len > sizeof(state->data)) {
+ warn("i2c rd: len=%d is too big!\n",
+ msg[1].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
state->data[0] = 0x09;
state->data[1] = msg[0].len;
state->data[2] = msg[1].len;