diff options
author | Alyssa Milburn <amilburn@zall.org> | 2017-04-01 20:34:49 +0300 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2017-08-26 04:14:02 +0300 |
commit | 716e324b700b885a6692b38d113329b61788d2d5 (patch) | |
tree | 7002c490d53cf1d4cbb98d0d3e7684e5f369042b /drivers | |
parent | 45fd70b4099514d51b117b87e03091ffcef96a5c (diff) | |
download | linux-716e324b700b885a6692b38d113329b61788d2d5.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>
[bwh: Backported to 3.2:
- Use obuf instead of state->data
- Adjust filename, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/dvb-usb/dw2102.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 477f9eff42f5..e0b3d37e3f03 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -234,6 +234,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; @@ -249,6 +263,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; @@ -292,6 +313,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); @@ -492,6 +520,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); @@ -718,6 +752,13 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], msg[0].buf[0] = ibuf[1]; break; default: + if (3 + msg[0].len > sizeof(obuf)) { + warn("i2c wr: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + /* always i2c write*/ obuf[0] = 0x08; obuf[1] = msg[0].addr; @@ -733,6 +774,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(obuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + if (1 + msg[1].len > sizeof(obuf)) { + warn("i2c rd: len=%d is too big!\n", + msg[1].len); + num = -EOPNOTSUPP; + break; + } + obuf[0] = 0x09; obuf[1] = msg[0].len; obuf[2] = msg[1].len; |