[PATCH] media: dw2102: fix OOB read on firmware size not a multiple of 64

Vasileios Almpanis <[email protected]>
Newsgroups org.kernel.vger.stable,org.kernel.vger.linux-kernel,org.kernel.vger.linux-media
Message-ID <[email protected]>
dw2102_load_firmware() copies the firmware into a buffer of exactly
fw->size bytes, then walks it in 0x40-byte steps while always passing
0x40 as the transfer length. When fw->size is not a multiple of 64 the
last chunk reads past the end of the allocation producing the following
splat:

  dvb-usb: downloading firmware from file 'dvb-usb-dw3101.fw'
  dw2102: start downloading DW210X firmware
  ==================================================================
  BUG: KASAN: slab-out-of-bounds in dw210x_op_rw+0xb6/0x180 drivers/media/usb/dvb-usb/dw2102.c:102
  Read of size 64 at addr ffff88802bcf2ba0 by task kworker/1:2/803
  Call Trace:
   <TASK>
   kasan_report+0x117/0x150 mm/kasan/report.c:595
   check_region_inline mm/kasan/generic.c:-1 [inline]
   kasan_check_range+0x264/0x2c0 mm/kasan/generic.c:200
   __asan_memcpy+0x29/0x70 mm/kasan/shadow.c:105
   dw210x_op_rw+0xb6/0x180 drivers/media/usb/dvb-usb/dw2102.c:102
   dw2102_load_firmware+0x2b4/0x970 drivers/media/usb/dvb-usb/dw2102.c:1906

Fix this by clamping the last chunk to the remaining bytes;

Cc: [email protected]
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=f408eac9faa61d5a1927
Fixes: 7fd4828f6cc5 ("V4L/DVB (8421): Adds support for Dvbworld DVB-S 2102 USB card")
Signed-off-by: Vasileios Almpanis <[email protected]>
---
 drivers/media/usb/dvb-usb/dw2102.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 4fecf2f965e9..4e26e1776977 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -1902,9 +1902,11 @@ static int dw2102_load_firmware(struct usb_device *dev,
 	if (p) {
 		memcpy(p, fw->data, fw->size);
 		for (i = 0; i < fw->size; i += 0x40) {
+			int len = min_t(size_t, fw->size - i, 0x40);
+
 			b = (u8 *)p + i;
-			if (dw210x_op_rw(dev, 0xa0, i, 0, b, 0x40,
-					 DW210X_WRITE_MSG) != 0x40) {
+			if (dw210x_op_rw(dev, 0xa0, i, 0, b, len,
+					 DW210X_WRITE_MSG) != len) {
 				err("error while transferring firmware");
 				ret = -EINVAL;
 				break;

---
base-commit: fcaeecb8b0cd44f77d03b28de0671258d4db18f8
change-id: 20260806-dvb-307714ff6225

Best regards,
--  
Vasileios Almpanis <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.