On Mon Jan 13 13:51:31 2025 +0300, Murad Masimov wrote:
> If streamzap_callback() receives an urb with any non-critical error
> status, i.e. any error code other than -ECONNRESET, -ENOENT or -ESHUTDOWN,
> it will try to process IR data, ignoring a possible transfer failure.
> 
> Make streamzap_callback() process IR data only when urb->status is 0.
> Move processing logic to a separate function to make code cleaner and
> more similar to the URB completion handlers in other RC drivers.
> 
> Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
> 
> Fixes: 19770693c354 ("V4L/DVB: staging/lirc: add lirc_streamzap driver")
> Cc: sta...@vger.kernel.org
> Signed-off-by: Murad Masimov <m.masi...@mt-integration.ru>
> Signed-off-by: Sean Young <s...@mess.org>
> Signed-off-by: Hans Verkuil <hverk...@xs4all.nl>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/rc/streamzap.c | 68 +++++++++++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 30 deletions(-)

---

diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index 2ce62fe5d60f..d3b48a0dd1f4 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -138,39 +138,10 @@ static void sz_push_half_space(struct streamzap_ir *sz,
        sz_push_full_space(sz, value & SZ_SPACE_MASK);
 }
 
-/*
- * streamzap_callback - usb IRQ handler callback
- *
- * This procedure is invoked on reception of data from
- * the usb remote.
- */
-static void streamzap_callback(struct urb *urb)
+static void sz_process_ir_data(struct streamzap_ir *sz, int len)
 {
-       struct streamzap_ir *sz;
        unsigned int i;
-       int len;
-
-       if (!urb)
-               return;
-
-       sz = urb->context;
-       len = urb->actual_length;
-
-       switch (urb->status) {
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /*
-                * this urb is terminated, clean up.
-                * sz might already be invalid at this point
-                */
-               dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
-               return;
-       default:
-               break;
-       }
 
-       dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
        for (i = 0; i < len; i++) {
                dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
                        i, (unsigned char)sz->buf_in[i]);
@@ -219,6 +190,43 @@ static void streamzap_callback(struct urb *urb)
        }
 
        ir_raw_event_handle(sz->rdev);
+}
+
+/*
+ * streamzap_callback - usb IRQ handler callback
+ *
+ * This procedure is invoked on reception of data from
+ * the usb remote.
+ */
+static void streamzap_callback(struct urb *urb)
+{
+       struct streamzap_ir *sz;
+       int len;
+
+       if (!urb)
+               return;
+
+       sz = urb->context;
+       len = urb->actual_length;
+
+       switch (urb->status) {
+       case 0:
+               dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
+               sz_process_ir_data(sz, len);
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /*
+                * this urb is terminated, clean up.
+                * sz might already be invalid at this point
+                */
+               dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
+               return;
+       default:
+               break;
+       }
+
        usb_submit_urb(urb, GFP_ATOMIC);
 }
 

Reply via email to