diff options
author | Alyssa Milburn <amilburn@zall.org> | 2017-04-01 13:34:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-25 09:44:42 -0400 |
commit | 40616929f87e1bb236f5daa0dffa3a95553ac76a (patch) | |
tree | ab79d6cb541a249d15263f9231a54593a40b7b86 | |
parent | e42a6715d26bc777b545018d585333ee91cdbbe9 (diff) |
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>
-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 c3e67347a977..4a0cc54870c7 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, | |||
205 | 205 | ||
206 | switch (num) { | 206 | switch (num) { |
207 | case 2: | 207 | case 2: |
208 | if (msg[0].len != 1) { | ||
209 | warn("i2c rd: len=%d is not 1!\n", | ||
210 | msg[0].len); | ||
211 | num = -EOPNOTSUPP; | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | if (2 + msg[1].len > sizeof(buf6)) { | ||
216 | warn("i2c rd: len=%d is too big!\n", | ||
217 | msg[1].len); | ||
218 | num = -EOPNOTSUPP; | ||
219 | break; | ||
220 | } | ||
221 | |||
208 | /* read si2109 register by number */ | 222 | /* read si2109 register by number */ |
209 | buf6[0] = msg[0].addr << 1; | 223 | buf6[0] = msg[0].addr << 1; |
210 | buf6[1] = msg[0].len; | 224 | buf6[1] = msg[0].len; |
@@ -220,6 +234,13 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, | |||
220 | case 1: | 234 | case 1: |
221 | switch (msg[0].addr) { | 235 | switch (msg[0].addr) { |
222 | case 0x68: | 236 | case 0x68: |
237 | if (2 + msg[0].len > sizeof(buf6)) { | ||
238 | warn("i2c wr: len=%d is too big!\n", | ||
239 | msg[0].len); | ||
240 | num = -EOPNOTSUPP; | ||
241 | break; | ||
242 | } | ||
243 | |||
223 | /* write to si2109 register */ | 244 | /* write to si2109 register */ |
224 | buf6[0] = msg[0].addr << 1; | 245 | buf6[0] = msg[0].addr << 1; |
225 | buf6[1] = msg[0].len; | 246 | buf6[1] = msg[0].len; |
@@ -263,6 +284,13 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms | |||
263 | /* first write first register number */ | 284 | /* first write first register number */ |
264 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; | 285 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; |
265 | 286 | ||
287 | if (2 + msg[0].len != sizeof(obuf)) { | ||
288 | warn("i2c rd: len=%d is not 1!\n", | ||
289 | msg[0].len); | ||
290 | ret = -EOPNOTSUPP; | ||
291 | goto unlock; | ||
292 | } | ||
293 | |||
266 | if (2 + msg[1].len > sizeof(ibuf)) { | 294 | if (2 + msg[1].len > sizeof(ibuf)) { |
267 | warn("i2c rd: len=%d is too big!\n", | 295 | warn("i2c rd: len=%d is too big!\n", |
268 | msg[1].len); | 296 | msg[1].len); |
@@ -463,6 +491,12 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
463 | /* first write first register number */ | 491 | /* first write first register number */ |
464 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; | 492 | u8 ibuf[MAX_XFER_SIZE], obuf[3]; |
465 | 493 | ||
494 | if (2 + msg[0].len != sizeof(obuf)) { | ||
495 | warn("i2c rd: len=%d is not 1!\n", | ||
496 | msg[0].len); | ||
497 | ret = -EOPNOTSUPP; | ||
498 | goto unlock; | ||
499 | } | ||
466 | if (2 + msg[1].len > sizeof(ibuf)) { | 500 | if (2 + msg[1].len > sizeof(ibuf)) { |
467 | warn("i2c rd: len=%d is too big!\n", | 501 | warn("i2c rd: len=%d is too big!\n", |
468 | msg[1].len); | 502 | msg[1].len); |
@@ -697,6 +731,13 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
697 | msg[0].buf[0] = state->data[1]; | 731 | msg[0].buf[0] = state->data[1]; |
698 | break; | 732 | break; |
699 | default: | 733 | default: |
734 | if (3 + msg[0].len > sizeof(state->data)) { | ||
735 | warn("i2c wr: len=%d is too big!\n", | ||
736 | msg[0].len); | ||
737 | num = -EOPNOTSUPP; | ||
738 | break; | ||
739 | } | ||
740 | |||
700 | /* always i2c write*/ | 741 | /* always i2c write*/ |
701 | state->data[0] = 0x08; | 742 | state->data[0] = 0x08; |
702 | state->data[1] = msg[0].addr; | 743 | state->data[1] = msg[0].addr; |
@@ -712,6 +753,19 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
712 | break; | 753 | break; |
713 | case 2: | 754 | case 2: |
714 | /* always i2c read */ | 755 | /* always i2c read */ |
756 | if (4 + msg[0].len > sizeof(state->data)) { | ||
757 | warn("i2c rd: len=%d is too big!\n", | ||
758 | msg[0].len); | ||
759 | num = -EOPNOTSUPP; | ||
760 | break; | ||
761 | } | ||
762 | if (1 + msg[1].len > sizeof(state->data)) { | ||
763 | warn("i2c rd: len=%d is too big!\n", | ||
764 | msg[1].len); | ||
765 | num = -EOPNOTSUPP; | ||
766 | break; | ||
767 | } | ||
768 | |||
715 | state->data[0] = 0x09; | 769 | state->data[0] = 0x09; |
716 | state->data[1] = msg[0].len; | 770 | state->data[1] = msg[0].len; |
717 | state->data[2] = msg[1].len; | 771 | state->data[2] = msg[1].len; |