USB: w1 ds2490: Fix bug caused by improper use of altsetting array [Linux 3.16.72]

This Linux kernel change "USB: w1 ds2490: Fix bug caused by improper use of altsetting array" is included in the Linux 3.16.72 release. This change is authored by Alan Stern <stern [at] rowland.harvard.edu> on Mon Apr 22 11:16:04 2019 -0400. The commit for this change in Linux stable tree is ef6b713 (patch) which is from upstream commit c114944. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream c114944.

USB: w1 ds2490: Fix bug caused by improper use of altsetting array

commit c114944d7d67f24e71562fcfc18d550ab787e4d4 upstream.

The syzkaller USB fuzzer spotted a slab-out-of-bounds bug in the
ds2490 driver.  This bug is caused by improper use of the altsetting
array in the usb_interface structure (the array's entries are not
always stored in numerical order), combined with a naive assumption
that all interfaces probed by the driver will have the expected number
of altsettings.

The bug can be fixed by replacing references to the possibly
non-existent intf->altsetting[alt] entry with the guaranteed-to-exist
intf->cur_altsetting entry.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-and-tested-by: syzbot+d65f673b847a1a96cdba@syzkaller.appspotmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

There are 6 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/w1/masters/ds2490.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 176b88f..ed420aa 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -1041,15 +1041,15 @@ static int ds_probe(struct usb_interface *intf,
    /* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */
    alt = 3;
    err = usb_set_interface(dev->udev,
-       intf->altsetting[alt].desc.bInterfaceNumber, alt);
+       intf->cur_altsetting->desc.bInterfaceNumber, alt);
    if (err) {
        dev_err(&dev->udev->dev, "Failed to set alternative setting %d "
            "for %d interface: err=%d.\n", alt,
-           intf->altsetting[alt].desc.bInterfaceNumber, err);
+           intf->cur_altsetting->desc.bInterfaceNumber, err);
        goto err_out_clear;
    }

-   iface_desc = &intf->altsetting[alt];
+   iface_desc = intf->cur_altsetting;
    if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
        printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
        err = -EINVAL;

Leave a Reply

Your email address will not be published. Required fields are marked *