]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: streamzap: prevent processing IR data on URB failure
authorMurad Masimov <m.masimov@mt-integration.ru>
Mon, 13 Jan 2025 10:51:31 +0000 (13:51 +0300)
committerHans Verkuil <hverkuil@xs4all.nl>
Thu, 13 Feb 2025 11:12:30 +0000 (12:12 +0100)
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: stable@vger.kernel.org
Signed-off-by: Murad Masimov <m.masimov@mt-integration.ru>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
drivers/media/rc/streamzap.c

index 2ce62fe5d60f5a8eb1d2381fc773bdf21df09a9b..d3b48a0dd1f474fbc7833276ff856dd8e07c4b41 100644 (file)
@@ -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);
 }