• Zheng Yejian's avatar
    media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control() · 2052138b
    Zheng Yejian authored
    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: 4d43e13f ("V4L/DVB (4643): Multi-input patch for DVB-USB device")
    Signed-off-by: default avatarZheng Yejian <zhengyejian1@huawei.com>
    Signed-off-by: default avatarSean Young <sean@mess.org>
    Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
    2052138b
dvb-usb-init.c 10.3 KB