Patch "media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control()" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control()

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     media-dvb-usb-fix-unexpected-infinite-loop-in-dvb_us.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 7d98e40133b254d22700d0d147deef9470ace5af
Author: Zheng Yejian <zhengyejian1@xxxxxxxxxx>
Date:   Thu May 9 20:44:14 2024 +0800

    media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control()
    
    [ Upstream commit 2052138b7da52ad5ccaf74f736d00f39a1c9198c ]
    
    Infinite log printing occurs during fuzz test:
    
      rc rc1: DViCO FusionHDTV DVB-T USB (LGZ201) as ...
      ...
      dvb-usb: schedule remote query interval to 100 msecs.
      dvb-usb: DViCO FusionHDTV DVB-T USB (LGZ201) successfully initialized ...
      dvb-usb: bulk message failed: -22 (1/0)
      dvb-usb: bulk message failed: -22 (1/0)
      dvb-usb: bulk message failed: -22 (1/0)
      ...
      dvb-usb: bulk message failed: -22 (1/0)
    
    Looking into the codes, there is a loop in dvb_usb_read_remote_control(),
    that is in rc_core_dvb_usb_remote_init() create a work that will call
    dvb_usb_read_remote_control(), and this work will reschedule itself at
    'rc_interval' intervals to recursively call dvb_usb_read_remote_control(),
    see following code snippet:
    
      rc_core_dvb_usb_remote_init() {
        ...
        INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
        schedule_delayed_work(&d->rc_query_work,
                              msecs_to_jiffies(rc_interval));
        ...
      }
    
      dvb_usb_read_remote_control() {
        ...
        err = d->props.rc.core.rc_query(d);
        if (err)
          err(...)  // Did not return even if query failed
        schedule_delayed_work(&d->rc_query_work,
                              msecs_to_jiffies(rc_interval));
      }
    
    When the infinite log printing occurs, the query callback
    'd->props.rc.core.rc_query' is cxusb_rc_query(). And the log is due to
    the failure of finding a valid 'generic_bulk_ctrl_endpoint'
    in usb_bulk_msg(), see following code snippet:
    
      cxusb_rc_query() {
        cxusb_ctrl_msg() {
          dvb_usb_generic_rw() {
            ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
                               d->props.generic_bulk_ctrl_endpoint),...);
            if (ret)
              err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
              ...
          }
      ...
      }
    
    By analyzing the corresponding USB descriptor, it shows that the
    bNumEndpoints is 0 in its interface descriptor, but
    the 'generic_bulk_ctrl_endpoint' is 1, that means user don't configure
    a valid endpoint for 'generic_bulk_ctrl_endpoint', therefore this
    'invalid' USB device should be rejected before it calls into
    dvb_usb_read_remote_control().
    
    To fix it, we need to add endpoint check for 'generic_bulk_ctrl_endpoint'.
    And as Sean suggested, the same check and clear halts should be done for
    'generic_bulk_ctrl_endpoint_response'. So introduce
    dvb_usb_check_bulk_endpoint() to do it for both of them.
    
    Fixes: 4d43e13f723e ("V4L/DVB (4643): Multi-input patch for DVB-USB device")
    Signed-off-by: Zheng Yejian <zhengyejian1@xxxxxxxxxx>
    Signed-off-by: Sean Young <sean@xxxxxxxx>
    Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c
index cb5bf119df9f1..6c7a56b178e52 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c
@@ -23,11 +23,40 @@ static int dvb_usb_force_pid_filter_usage;
 module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
 MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
 
+static int dvb_usb_check_bulk_endpoint(struct dvb_usb_device *d, u8 endpoint)
+{
+	if (endpoint) {
+		int ret;
+
+		ret = usb_pipe_type_check(d->udev, usb_sndbulkpipe(d->udev, endpoint));
+		if (ret)
+			return ret;
+		ret = usb_pipe_type_check(d->udev, usb_rcvbulkpipe(d->udev, endpoint));
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static void dvb_usb_clear_halt(struct dvb_usb_device *d, u8 endpoint)
+{
+	if (endpoint) {
+		usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, endpoint));
+		usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, endpoint));
+	}
+}
+
 static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 {
 	struct dvb_usb_adapter *adap;
 	int ret, n, o;
 
+	ret = dvb_usb_check_bulk_endpoint(d, d->props.generic_bulk_ctrl_endpoint);
+	if (ret)
+		return ret;
+	ret = dvb_usb_check_bulk_endpoint(d, d->props.generic_bulk_ctrl_endpoint_response);
+	if (ret)
+		return ret;
 	for (n = 0; n < d->props.num_adapters; n++) {
 		adap = &d->adapter[n];
 		adap->dev = d;
@@ -103,10 +132,8 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 	 * when reloading the driver w/o replugging the device
 	 * sometimes a timeout occurs, this helps
 	 */
-	if (d->props.generic_bulk_ctrl_endpoint != 0) {
-		usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-		usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	}
+	dvb_usb_clear_halt(d, d->props.generic_bulk_ctrl_endpoint);
+	dvb_usb_clear_halt(d, d->props.generic_bulk_ctrl_endpoint_response);
 
 	return 0;
 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux