3.2.92-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Alyssa Milburn <amilburn@xxxxxxxx> 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@xxxxxxxx> Signed-off-by: Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxxxxx> [bwh: Backported to 3.2: - Use obuf instead of state->data - Adjust filename, context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- drivers/media/dvb/dvb-usb/dw2102.c | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) --- 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(str 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(str 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(str /* 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 i2 /* 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 i2 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 i2 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;