diff options
author | Alyssa Milburn <amilburn@zall.org> | 2017-04-01 13:34:49 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-04-19 06:03:20 -0400 |
commit | 950e252cb469f323740d78e4907843acef89eedb (patch) | |
tree | 5cf80f6b6b29f0298017a6a00721184fcde8a9b3 /drivers/media | |
parent | a12b8ab8c5ff7ccd7b107a564743507c850a441d (diff) |
[media] dw2102: limit messages to buffer size
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>
Cc: stable@vger.kernel.org
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/usb/dvb-usb/dw2102.c | 54 |
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 4f42d57f81d9..6e654e5026dd 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c | |||
@@ -204,6 +204,20 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, | |||
204 | 204 | ||
205 | switch (num) { | 205 | switch (num) { |
206 | case 2: | 206 | case 2: |
207 | if (msg[0].len != 1) { | ||
208 | warn("i2c rd: len=%d is not 1!\n", | ||
209 | msg[0].len); | ||
210 | num = -EOPNOTSUPP; | ||
211 | break; | ||
212 | } | ||
213 | |||
214 | if (2 + msg[1].len > sizeof(buf6)) { | ||
215 | warn("i2c rd: len=%d is too big!\n", | ||
216 | msg[1].len); | ||
217 | num = -EOPNOTSUPP; | ||
218 | break; | ||
219 | } | ||
220 | |||
207 | /* read si2109 register by number */ | 221 | /* read si2109 register by number */ |
208 | buf6[0] = msg[0].addr << 1; | 222 | buf6[0] = msg[0].addr << 1; |
209 | buf6[1] = msg[0].len; | 223 | buf6[1] = msg[0].len; |
@@ -219,6 +233,13 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, | |||
219 | case 1: | 233 | case 1: |
220 | switch (msg[0].addr) { | 234 | switch (msg[0].addr) { |
221 | case 0x68: | 235 | case 0x68: |
236 | if (2 + msg[0].len > sizeof(buf6)) { | ||
237 | warn("i2c wr: len=%d is too big!\n", | ||
238 | msg[0].len); | ||
239 | num = -EOPNOTSUPP; | ||
240 | break; | ||
241 | } | ||
242 | |||
222 | /* write to si2109 register */ | 243 | /* write to si2109 register */ |
223 | buf6[0] = msg[0].addr << 1; | 244 | buf6[0] = msg[0].addr << 1; |
224 | buf6[1] = msg[0].len; | 245 | buf6[1] = msg[0].len; |
@@ -262,6 +283,13 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms | |||
262 | /* first write first register number */ | 283 | /* first write first register number */ |
263 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; | 284 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; |
264 | 285 | ||
286 | if (2 + msg[0].len != sizeof(obuf)) { | ||
287 | warn("i2c rd: len=%d is not 1!\n", | ||
288 | msg[0].len); | ||
289 | ret = -EOPNOTSUPP; | ||
290 | goto unlock; | ||
291 | } | ||
292 | |||
265 | if (2 + msg[1].len > sizeof(ibuf)) { | 293 | if (2 + msg[1].len > sizeof(ibuf)) { |
266 | warn("i2c rd: len=%d is too big!\n", | 294 | warn("i2c rd: len=%d is too big!\n", |
267 | msg[1].len); | 295 | msg[1].len); |
@@ -462,6 +490,12 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
462 | /* first write first register number */ | 490 | /* first write first register number */ |
463 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; | 491 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; |
464 | 492 | ||
493 | if (2 + msg[0].len != sizeof(obuf)) { | ||
494 | warn("i2c rd: len=%d is not 1!\n", | ||
495 | msg[0].len); | ||
496 | ret = -EOPNOTSUPP; | ||
497 | goto unlock; | ||
498 | } | ||
465 | if (2 + msg[1].len > sizeof(ibuf)) { | 499 | if (2 + msg[1].len > sizeof(ibuf)) { |
466 | warn("i2c rd: len=%d is too big!\n", | 500 | warn("i2c rd: len=%d is too big!\n", |
467 | msg[1].len); | 501 | msg[1].len); |
@@ -696,6 +730,13 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
696 | msg[0].buf[0] = state->data[1]; | 730 | msg[0].buf[0] = state->data[1]; |
697 | break; | 731 | break; |
698 | default: | 732 | default: |
733 | if (3 + msg[0].len > sizeof(state->data)) { | ||
734 | warn("i2c wr: len=%d is too big!\n", | ||
735 | msg[0].len); | ||
736 | num = -EOPNOTSUPP; | ||
737 | break; | ||
738 | } | ||
739 | |||
699 | /* always i2c write*/ | 740 | /* always i2c write*/ |
700 | state->data[0] = 0x08; | 741 | state->data[0] = 0x08; |
701 | state->data[1] = msg[0].addr; | 742 | state->data[1] = msg[0].addr; |
@@ -711,6 +752,19 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
711 | break; | 752 | break; |
712 | case 2: | 753 | case 2: |
713 | /* always i2c read */ | 754 | /* always i2c read */ |
755 | if (4 + msg[0].len > sizeof(state->data)) { | ||
756 | warn("i2c rd: len=%d is too big!\n", | ||
757 | msg[0].len); | ||
758 | num = -EOPNOTSUPP; | ||
759 | break; | ||
760 | } | ||
761 | if (1 + msg[1].len > sizeof(state->data)) { | ||
762 | warn("i2c rd: len=%d is too big!\n", | ||
763 | msg[1].len); | ||
764 | num = -EOPNOTSUPP; | ||
765 | break; | ||
766 | } | ||
767 | |||
714 | state->data[0] = 0x09; | 768 | state->data[0] = 0x09; |
715 | state->data[1] = msg[0].len; | 769 | state->data[1] = msg[0].len; |
716 | state->data[2] = msg[1].len; | 770 | state->data[2] = msg[1].len; |