--- /dev/null
+From ca8f245f284eeffa56f3b7a5eb6fc503159ee028 Mon Sep 17 00:00:00 2001
+From: Vito Caputo <vcaputo@pengaru.com>
+Date: Sun, 13 Oct 2019 23:08:45 -0300
+Subject: media: cxusb: detect cxusb_ctrl_msg error in query
+
+From: Vito Caputo <vcaputo@pengaru.com>
+
+commit ca8f245f284eeffa56f3b7a5eb6fc503159ee028 upstream.
+
+Don't use uninitialized ircode[] in cxusb_rc_query() when
+cxusb_ctrl_msg() fails to populate its contents.
+
+syzbot reported:
+
+dvb-usb: bulk message failed: -22 (1/-30591)
+=====================================================
+BUG: KMSAN: uninit-value in ir_lookup_by_scancode drivers/media/rc/rc-main.c:494 [inline]
+BUG: KMSAN: uninit-value in rc_g_keycode_from_table drivers/media/rc/rc-main.c:582 [inline]
+BUG: KMSAN: uninit-value in rc_keydown+0x1a6/0x6f0 drivers/media/rc/rc-main.c:816
+CPU: 1 PID: 11436 Comm: kworker/1:2 Not tainted 5.3.0-rc7+ #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+Workqueue: events dvb_usb_read_remote_control
+Call Trace:
+ __dump_stack lib/dump_stack.c:77 [inline]
+ dump_stack+0x191/0x1f0 lib/dump_stack.c:113
+ kmsan_report+0x13a/0x2b0 mm/kmsan/kmsan_report.c:108
+ __msan_warning+0x73/0xe0 mm/kmsan/kmsan_instr.c:250
+ bsearch+0x1dd/0x250 lib/bsearch.c:41
+ ir_lookup_by_scancode drivers/media/rc/rc-main.c:494 [inline]
+ rc_g_keycode_from_table drivers/media/rc/rc-main.c:582 [inline]
+ rc_keydown+0x1a6/0x6f0 drivers/media/rc/rc-main.c:816
+ cxusb_rc_query+0x2e1/0x360 drivers/media/usb/dvb-usb/cxusb.c:548
+ dvb_usb_read_remote_control+0xf9/0x290 drivers/media/usb/dvb-usb/dvb-usb-remote.c:261
+ process_one_work+0x1572/0x1ef0 kernel/workqueue.c:2269
+ worker_thread+0x111b/0x2460 kernel/workqueue.c:2415
+ kthread+0x4b5/0x4f0 kernel/kthread.c:256
+ ret_from_fork+0x35/0x40 arch/x86/entry/entry_64.S:355
+
+Uninit was stored to memory at:
+ kmsan_save_stack_with_flags mm/kmsan/kmsan.c:150 [inline]
+ kmsan_internal_chain_origin+0xd2/0x170 mm/kmsan/kmsan.c:314
+ __msan_chain_origin+0x6b/0xe0 mm/kmsan/kmsan_instr.c:184
+ rc_g_keycode_from_table drivers/media/rc/rc-main.c:583 [inline]
+ rc_keydown+0x2c4/0x6f0 drivers/media/rc/rc-main.c:816
+ cxusb_rc_query+0x2e1/0x360 drivers/media/usb/dvb-usb/cxusb.c:548
+ dvb_usb_read_remote_control+0xf9/0x290 drivers/media/usb/dvb-usb/dvb-usb-remote.c:261
+ process_one_work+0x1572/0x1ef0 kernel/workqueue.c:2269
+ worker_thread+0x111b/0x2460 kernel/workqueue.c:2415
+ kthread+0x4b5/0x4f0 kernel/kthread.c:256
+ ret_from_fork+0x35/0x40 arch/x86/entry/entry_64.S:355
+
+Local variable description: ----ircode@cxusb_rc_query
+Variable was created at:
+ cxusb_rc_query+0x4d/0x360 drivers/media/usb/dvb-usb/cxusb.c:543
+ dvb_usb_read_remote_control+0xf9/0x290 drivers/media/usb/dvb-usb/dvb-usb-remote.c:261
+
+Signed-off-by: Vito Caputo <vcaputo@pengaru.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/dvb-usb/cxusb.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/usb/dvb-usb/cxusb.c
++++ b/drivers/media/usb/dvb-usb/cxusb.c
+@@ -521,7 +521,8 @@ static int cxusb_rc_query(struct dvb_usb
+ {
+ u8 ircode[4];
+
+- cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
++ if (cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4) < 0)
++ return 0;
+
+ if (ircode[2] || ircode[3])
+ rc_keydown(d->rc_dev, RC_PROTO_NEC,
--- /dev/null
+From f3f5ba42c58d56d50f539854d8cc188944e96087 Mon Sep 17 00:00:00 2001
+From: Sean Young <sean@mess.org>
+Date: Wed, 16 Oct 2019 14:19:15 -0300
+Subject: media: imon: invalid dereference in imon_touch_event
+
+From: Sean Young <sean@mess.org>
+
+commit f3f5ba42c58d56d50f539854d8cc188944e96087 upstream.
+
+The touch timer is set up in intf1. If the second interface does not exist,
+the timer and touch input device are not setup and we get the following
+error, when touch events are reported via intf0.
+
+kernel BUG at kernel/time/timer.c:956!
+invalid opcode: 0000 [#1] SMP KASAN
+CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.0-rc1+ #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+RIP: 0010:__mod_timer kernel/time/timer.c:956 [inline]
+RIP: 0010:__mod_timer kernel/time/timer.c:949 [inline]
+RIP: 0010:mod_timer+0x5a2/0xb50 kernel/time/timer.c:1100
+Code: 45 10 c7 44 24 14 ff ff ff ff 48 89 44 24 08 48 8d 45 20 48 c7 44 24 18 00 00 00 00 48 89 04 24 e9 5a fc ff ff e8 ae ce 0e 00 <0f> 0b e8 a7 ce 0e 00 4c 89 74 24 20 e9 37 fe ff ff e8 98 ce 0e 00
+RSP: 0018:ffff8881db209930 EFLAGS: 00010006
+RAX: ffffffff86c2b200 RBX: 00000000ffffa688 RCX: ffffffff83efc583
+RDX: 0000000000000100 RSI: ffffffff812f4d82 RDI: ffff8881d2356200
+RBP: ffff8881d23561e8 R08: ffffffff86c2b200 R09: ffffed103a46abeb
+R10: ffffed103a46abea R11: ffff8881d2355f53 R12: dffffc0000000000
+R13: 1ffff1103b64132d R14: ffff8881d2355f50 R15: 0000000000000006
+FS: 0000000000000000(0000) GS:ffff8881db200000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f75e2799000 CR3: 00000001d3b07000 CR4: 00000000001406f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <IRQ>
+ imon_touch_event drivers/media/rc/imon.c:1348 [inline]
+ imon_incoming_packet.isra.0+0x2546/0x2f10 drivers/media/rc/imon.c:1603
+ usb_rx_callback_intf0+0x151/0x1e0 drivers/media/rc/imon.c:1734
+ __usb_hcd_giveback_urb+0x1f2/0x470 drivers/usb/core/hcd.c:1654
+ usb_hcd_giveback_urb+0x368/0x420 drivers/usb/core/hcd.c:1719
+ dummy_timer+0x120f/0x2fa2 drivers/usb/gadget/udc/dummy_hcd.c:1965
+ call_timer_fn+0x179/0x650 kernel/time/timer.c:1404
+ expire_timers kernel/time/timer.c:1449 [inline]
+ __run_timers kernel/time/timer.c:1773 [inline]
+ __run_timers kernel/time/timer.c:1740 [inline]
+ run_timer_softirq+0x5e3/0x1490 kernel/time/timer.c:1786
+ __do_softirq+0x221/0x912 kernel/softirq.c:292
+ invoke_softirq kernel/softirq.c:373 [inline]
+ irq_exit+0x178/0x1a0 kernel/softirq.c:413
+ exiting_irq arch/x86/include/asm/apic.h:536 [inline]
+ smp_apic_timer_interrupt+0x12f/0x500 arch/x86/kernel/apic/apic.c:1137
+ apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:830
+ </IRQ>
+RIP: 0010:default_idle+0x28/0x2e0 arch/x86/kernel/process.c:581
+Code: 90 90 41 56 41 55 65 44 8b 2d 44 3a 8f 7a 41 54 55 53 0f 1f 44 00 00 e8 36 ee d0 fb e9 07 00 00 00 0f 00 2d fa dd 4f 00 fb f4 <65> 44 8b 2d 20 3a 8f 7a 0f 1f 44 00 00 5b 5d 41 5c 41 5d 41 5e c3
+RSP: 0018:ffffffff86c07da8 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff13
+RAX: 0000000000000007 RBX: ffffffff86c2b200 RCX: 0000000000000000
+RDX: 0000000000000000 RSI: 0000000000000006 RDI: ffffffff86c2ba4c
+RBP: fffffbfff0d85640 R08: ffffffff86c2b200 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
+R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+ cpuidle_idle_call kernel/sched/idle.c:154 [inline]
+ do_idle+0x3b6/0x500 kernel/sched/idle.c:263
+ cpu_startup_entry+0x14/0x20 kernel/sched/idle.c:355
+ start_kernel+0x82a/0x864 init/main.c:784
+ secondary_startup_64+0xa4/0xb0 arch/x86/kernel/head_64.S:241
+Modules linked in:
+
+Reported-by: syzbot+f49d12d34f2321cf4df2@syzkaller.appspotmail.com
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/rc/imon.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -1598,8 +1598,7 @@ static void imon_incoming_packet(struct
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
+ /* send touchscreen events through input subsystem if touchpad data */
+- if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
+- buf[7] == 0x86) {
++ if (ictx->touch && len == 8 && buf[7] == 0x86) {
+ imon_touch_event(ictx, buf);
+ return;
+
--- /dev/null
+From e43148645d18efc3072b1ba45afaa3f385299e55 Mon Sep 17 00:00:00 2001
+From: A Sun <as1033x@comcast.net>
+Date: Fri, 6 Sep 2019 09:17:20 -0300
+Subject: media: mceusb: fix out of bounds read in MCE receiver buffer
+
+From: A Sun <as1033x@comcast.net>
+
+commit e43148645d18efc3072b1ba45afaa3f385299e55 upstream.
+
+Fix multiple cases of out of bounds (OOB) read associated with
+MCE device receive/input data handling.
+
+In reference for the OOB cases below, the incoming/read (byte) data
+format when the MCE device responds to a command is:
+ { cmd_prefix, subcmd, data0, data1, ... }
+where cmd_prefix are:
+ MCE_CMD_PORT_SYS
+ MCE_CMD_PORT_IR
+and subcmd examples are:
+ MCE_RSP_GETPORTSTATUS
+ MCE_RSP_EQIRNUMPORTS
+ ...
+Response size dynamically depends on cmd_prefix and subcmd.
+So data0, data1, ... may or may not be present on input.
+Multiple responses may return in a single receiver buffer.
+
+The trigger condition for OOB read is typically random or
+corrupt input data that fills the mceusb receiver buffer.
+
+Case 1:
+
+mceusb_handle_command() reads data0 (var hi) and data1 (var lo)
+regardless of whether the response includes such data.
+If { cmd_prefix, subcmd } is at the end of the receiver buffer,
+read past end of buffer occurs.
+
+This case was reported by
+KASAN: slab-out-of-bounds Read in mceusb_dev_recv
+https://syzkaller.appspot.com/bug?extid=c7fdb6cb36e65f2fe8c9
+
+Fix: In mceusb_handle_command(), change variable hi and lo to
+pointers, and dereference only when required.
+
+Case 2:
+
+If response with data is truncated at end of buffer after
+{ cmd_prefix, subcmd }, mceusb_handle_command() reads past
+end of buffer for data0, data1, ...
+
+Fix: In mceusb_process_ir_data(), check response size with
+remaining buffer size before invoking mceusb_handle_command().
++ if (i + ir->rem < buf_len)
+ mceusb_handle_command(ir, &ir->buf_in[i - 1]);
+
+Case 3:
+
+mceusb_handle_command() handles invalid/bad response such as
+{ 0x??, MCE_RSP_GETPORTSTATUS } of length 2 as a response
+{ MCE_CMD_PORT_SYS, MCE_RSP_GETPORTSTATUS, data0, ... }
+of length 7. Read OOB occurs for non-existent data0, data1, ...
+Cause is mceusb_handle_command() does not check cmd_prefix value.
+
+Fix: mceusb_handle_command() must test both cmd_prefix and subcmd.
+
+Case 4:
+
+mceusb_process_ir_data() receiver parser state SUBCMD is
+possible at start (i=0) of receiver buffer resulting in buffer
+offset=-1 passed to mceusb_dev_printdata().
+Bad offset results in OOB read before start of buffer.
+
+[1214218.580308] mceusb 1-1.3:1.0: rx data[0]: 00 80 (length=2)
+[1214218.580323] mceusb 1-1.3:1.0: Unknown command 0x00 0x80
+...
+[1214218.580406] mceusb 1-1.3:1.0: rx data[14]: 7f 7f (length=2)
+[1214218.679311] mceusb 1-1.3:1.0: rx data[-1]: 80 90 (length=2)
+[1214218.679325] mceusb 1-1.3:1.0: End of raw IR data
+[1214218.679340] mceusb 1-1.3:1.0: rx data[1]: 7f 7f (length=2)
+
+Fix: If parser_state is SUBCMD after processing receiver buffer,
+reset parser_state to CMD_HEADER.
+In effect, discard cmd_prefix at end of receiver buffer.
+In mceusb_dev_printdata(), abort if buffer offset is out of bounds.
+
+Case 5:
+
+If response with data is truncated at end of buffer after
+{ cmd_prefix, subcmd }, mceusb_dev_printdata() reads past
+end of buffer for data0, data1, ...
+while decoding the response to print out.
+
+Fix: In mceusb_dev_printdata(), remove unneeded buffer offset
+adjustments (var start and var skip) associated with MCE gen1 header.
+Test for truncated MCE cmd response (compare offset+len with buf_len)
+and skip decoding of incomplete response.
+Move IR data tracing to execute before the truncation test.
+
+Signed-off-by: A Sun <as1033x@comcast.net>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/rc/mceusb.c | 141 +++++++++++++++++++++++++++++++---------------
+ 1 file changed, 98 insertions(+), 43 deletions(-)
+
+--- a/drivers/media/rc/mceusb.c
++++ b/drivers/media/rc/mceusb.c
+@@ -564,7 +564,7 @@ static int mceusb_cmd_datasize(u8 cmd, u
+ datasize = 4;
+ break;
+ case MCE_CMD_G_REVISION:
+- datasize = 2;
++ datasize = 4;
+ break;
+ case MCE_RSP_EQWAKESUPPORT:
+ case MCE_RSP_GETWAKESOURCE:
+@@ -600,14 +600,9 @@ static void mceusb_dev_printdata(struct
+ char *inout;
+ u8 cmd, subcmd, *data;
+ struct device *dev = ir->dev;
+- int start, skip = 0;
+ u32 carrier, period;
+
+- /* skip meaningless 0xb1 0x60 header bytes on orig receiver */
+- if (ir->flags.microsoft_gen1 && !out && !offset)
+- skip = 2;
+-
+- if (len <= skip)
++ if (offset < 0 || offset >= buf_len)
+ return;
+
+ dev_dbg(dev, "%cx data[%d]: %*ph (len=%d sz=%d)",
+@@ -616,11 +611,32 @@ static void mceusb_dev_printdata(struct
+
+ inout = out ? "Request" : "Got";
+
+- start = offset + skip;
+- cmd = buf[start] & 0xff;
+- subcmd = buf[start + 1] & 0xff;
+- data = buf + start + 2;
++ cmd = buf[offset];
++ subcmd = (offset + 1 < buf_len) ? buf[offset + 1] : 0;
++ data = &buf[offset] + 2;
++
++ /* Trace meaningless 0xb1 0x60 header bytes on original receiver */
++ if (ir->flags.microsoft_gen1 && !out && !offset) {
++ dev_dbg(dev, "MCE gen 1 header");
++ return;
++ }
+
++ /* Trace IR data header or trailer */
++ if (cmd != MCE_CMD_PORT_IR &&
++ (cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA) {
++ if (cmd == MCE_IRDATA_TRAILER)
++ dev_dbg(dev, "End of raw IR data");
++ else
++ dev_dbg(dev, "Raw IR data, %d pulse/space samples",
++ cmd & MCE_PACKET_LENGTH_MASK);
++ return;
++ }
++
++ /* Unexpected end of buffer? */
++ if (offset + len > buf_len)
++ return;
++
++ /* Decode MCE command/response */
+ switch (cmd) {
+ case MCE_CMD_NULL:
+ if (subcmd == MCE_CMD_NULL)
+@@ -644,7 +660,7 @@ static void mceusb_dev_printdata(struct
+ dev_dbg(dev, "Get hw/sw rev?");
+ else
+ dev_dbg(dev, "hw/sw rev %*ph",
+- 4, &buf[start + 2]);
++ 4, &buf[offset + 2]);
+ break;
+ case MCE_CMD_RESUME:
+ dev_dbg(dev, "Device resume requested");
+@@ -746,13 +762,6 @@ static void mceusb_dev_printdata(struct
+ default:
+ break;
+ }
+-
+- if (cmd == MCE_IRDATA_TRAILER)
+- dev_dbg(dev, "End of raw IR data");
+- else if ((cmd != MCE_CMD_PORT_IR) &&
+- ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA))
+- dev_dbg(dev, "Raw IR data, %d pulse/space samples",
+- cmd & MCE_PACKET_LENGTH_MASK);
+ #endif
+ }
+
+@@ -1136,32 +1145,62 @@ static int mceusb_set_rx_carrier_report(
+ }
+
+ /*
++ * Handle PORT_SYS/IR command response received from the MCE device.
++ *
++ * Assumes single response with all its data (not truncated)
++ * in buf_in[]. The response itself determines its total length
++ * (mceusb_cmd_datasize() + 2) and hence the minimum size of buf_in[].
++ *
+ * We don't do anything but print debug spew for many of the command bits
+ * we receive from the hardware, but some of them are useful information
+ * we want to store so that we can use them.
+ */
+-static void mceusb_handle_command(struct mceusb_dev *ir, int index)
++static void mceusb_handle_command(struct mceusb_dev *ir, u8 *buf_in)
+ {
++ u8 cmd = buf_in[0];
++ u8 subcmd = buf_in[1];
++ u8 *hi = &buf_in[2]; /* read only when required */
++ u8 *lo = &buf_in[3]; /* read only when required */
+ struct ir_raw_event rawir = {};
+- u8 hi = ir->buf_in[index + 1] & 0xff;
+- u8 lo = ir->buf_in[index + 2] & 0xff;
+ u32 carrier_cycles;
+ u32 cycles_fix;
+
+- switch (ir->buf_in[index]) {
+- /* the one and only 5-byte return value command */
+- case MCE_RSP_GETPORTSTATUS:
+- if ((ir->buf_in[index + 4] & 0xff) == 0x00)
+- ir->txports_cabled |= 1 << hi;
+- break;
++ if (cmd == MCE_CMD_PORT_SYS) {
++ switch (subcmd) {
++ /* the one and only 5-byte return value command */
++ case MCE_RSP_GETPORTSTATUS:
++ if (buf_in[5] == 0)
++ ir->txports_cabled |= 1 << *hi;
++ break;
+
++ /* 1-byte return value commands */
++ case MCE_RSP_EQEMVER:
++ ir->emver = *hi;
++ break;
++
++ /* No return value commands */
++ case MCE_RSP_CMD_ILLEGAL:
++ ir->need_reset = true;
++ break;
++
++ default:
++ break;
++ }
++
++ return;
++ }
++
++ if (cmd != MCE_CMD_PORT_IR)
++ return;
++
++ switch (subcmd) {
+ /* 2-byte return value commands */
+ case MCE_RSP_EQIRTIMEOUT:
+- ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT);
++ ir->rc->timeout = US_TO_NS((*hi << 8 | *lo) * MCE_TIME_UNIT);
+ break;
+ case MCE_RSP_EQIRNUMPORTS:
+- ir->num_txports = hi;
+- ir->num_rxports = lo;
++ ir->num_txports = *hi;
++ ir->num_rxports = *lo;
+ break;
+ case MCE_RSP_EQIRRXCFCNT:
+ /*
+@@ -1174,7 +1213,7 @@ static void mceusb_handle_command(struct
+ */
+ if (ir->carrier_report_enabled && ir->learning_active &&
+ ir->pulse_tunit > 0) {
+- carrier_cycles = (hi << 8 | lo);
++ carrier_cycles = (*hi << 8 | *lo);
+ /*
+ * Adjust carrier cycle count by adding
+ * 1 missed count per pulse "on"
+@@ -1192,24 +1231,24 @@ static void mceusb_handle_command(struct
+ break;
+
+ /* 1-byte return value commands */
+- case MCE_RSP_EQEMVER:
+- ir->emver = hi;
+- break;
+ case MCE_RSP_EQIRTXPORTS:
+- ir->tx_mask = hi;
++ ir->tx_mask = *hi;
+ break;
+ case MCE_RSP_EQIRRXPORTEN:
+- ir->learning_active = ((hi & 0x02) == 0x02);
+- if (ir->rxports_active != hi) {
++ ir->learning_active = ((*hi & 0x02) == 0x02);
++ if (ir->rxports_active != *hi) {
+ dev_info(ir->dev, "%s-range (0x%x) receiver active",
+- ir->learning_active ? "short" : "long", hi);
+- ir->rxports_active = hi;
++ ir->learning_active ? "short" : "long", *hi);
++ ir->rxports_active = *hi;
+ }
+ break;
++
++ /* No return value commands */
+ case MCE_RSP_CMD_ILLEGAL:
+ case MCE_RSP_TX_TIMEOUT:
+ ir->need_reset = true;
+ break;
++
+ default:
+ break;
+ }
+@@ -1235,7 +1274,8 @@ static void mceusb_process_ir_data(struc
+ ir->rem = mceusb_cmd_datasize(ir->cmd, ir->buf_in[i]);
+ mceusb_dev_printdata(ir, ir->buf_in, buf_len, i - 1,
+ ir->rem + 2, false);
+- mceusb_handle_command(ir, i);
++ if (i + ir->rem < buf_len)
++ mceusb_handle_command(ir, &ir->buf_in[i - 1]);
+ ir->parser_state = CMD_DATA;
+ break;
+ case PARSE_IRDATA:
+@@ -1264,15 +1304,22 @@ static void mceusb_process_ir_data(struc
+ ir->rem--;
+ break;
+ case CMD_HEADER:
+- /* decode mce packets of the form (84),AA,BB,CC,DD */
+- /* IR data packets can span USB messages - rem */
+ ir->cmd = ir->buf_in[i];
+ if ((ir->cmd == MCE_CMD_PORT_IR) ||
+ ((ir->cmd & MCE_PORT_MASK) !=
+ MCE_COMMAND_IRDATA)) {
++ /*
++ * got PORT_SYS, PORT_IR, or unknown
++ * command response prefix
++ */
+ ir->parser_state = SUBCMD;
+ continue;
+ }
++ /*
++ * got IR data prefix (0x80 + num_bytes)
++ * decode MCE packets of the form {0x83, AA, BB, CC}
++ * IR data packets can span USB messages
++ */
+ ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
+ mceusb_dev_printdata(ir, ir->buf_in, buf_len,
+ i, ir->rem + 1, false);
+@@ -1296,6 +1343,14 @@ static void mceusb_process_ir_data(struc
+ if (ir->parser_state != CMD_HEADER && !ir->rem)
+ ir->parser_state = CMD_HEADER;
+ }
++
++ /*
++ * Accept IR data spanning multiple rx buffers.
++ * Reject MCE command response spanning multiple rx buffers.
++ */
++ if (ir->parser_state != PARSE_IRDATA || !ir->rem)
++ ir->parser_state = CMD_HEADER;
++
+ if (event) {
+ dev_dbg(ir->dev, "processed IR data");
+ ir_raw_event_handle(ir->rc);
--- /dev/null
+From 8c279e9394cade640ed86ec6c6645a0e7df5e0b6 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Mon, 29 Jul 2019 23:14:55 -0300
+Subject: media: uvcvideo: Fix error path in control parsing failure
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+commit 8c279e9394cade640ed86ec6c6645a0e7df5e0b6 upstream.
+
+When parsing the UVC control descriptors fails, the error path tries to
+cleanup a media device that hasn't been initialised, potentially
+resulting in a crash. Fix this by initialising the media device before
+the error handling path can be reached.
+
+Fixes: 5a254d751e52 ("[media] uvcvideo: Register a v4l2_device")
+Reported-by: syzbot+c86454eb3af9e8a4da20@syzkaller.appspotmail.com
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/uvc/uvc_driver.c | 28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+--- a/drivers/media/usb/uvc/uvc_driver.c
++++ b/drivers/media/usb/uvc/uvc_driver.c
+@@ -2151,6 +2151,20 @@ static int uvc_probe(struct usb_interfac
+ sizeof(dev->name) - len);
+ }
+
++ /* Initialize the media device. */
++#ifdef CONFIG_MEDIA_CONTROLLER
++ dev->mdev.dev = &intf->dev;
++ strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
++ if (udev->serial)
++ strscpy(dev->mdev.serial, udev->serial,
++ sizeof(dev->mdev.serial));
++ usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info));
++ dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
++ media_device_init(&dev->mdev);
++
++ dev->vdev.mdev = &dev->mdev;
++#endif
++
+ /* Parse the Video Class control descriptor. */
+ if (uvc_parse_control(dev) < 0) {
+ uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
+@@ -2171,19 +2185,7 @@ static int uvc_probe(struct usb_interfac
+ "linux-uvc-devel mailing list.\n");
+ }
+
+- /* Initialize the media device and register the V4L2 device. */
+-#ifdef CONFIG_MEDIA_CONTROLLER
+- dev->mdev.dev = &intf->dev;
+- strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
+- if (udev->serial)
+- strscpy(dev->mdev.serial, udev->serial,
+- sizeof(dev->mdev.serial));
+- usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info));
+- dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+- media_device_init(&dev->mdev);
+-
+- dev->vdev.mdev = &dev->mdev;
+-#endif
++ /* Register the V4L2 device. */
+ if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
+ goto error;
+