USB: fix NULL-deref and alternate settings bugs
Subsystems (5)
Johan Hovold
maintainercover USB: fix NULL-deref and alternate settings bugs
I stumbled over a couple potential NULL-pointer dereferences due to drivers using the first altsetting instead of the current one when doing descriptor sanity checks.
Turns out we have a quite a few drivers getting this wrong even if this would mostly be an issue on kernels with panic_on_warn set due to the WARN() in usb_submit_urb().
Since we've started backporting fixes for such warnings (e.g. as reported by syzbot), I've marked these for stable as well.
Johan
Johan Hovold (4):
USB: atm: ueagle-atm: add missing endpoint check
USB: adutux: fix interface sanity check
USB: idmouse: fix interface sanity checks
USB: serial: io_edgeport: fix epic endpoint lookup
drivers/usb/atm/ueagle-atm.c | 18 ++++++++++++------ drivers/usb/misc/adutux.c | 2 +- drivers/usb/misc/idmouse.c | 2 +- drivers/usb/serial/io_edgeport.c | 10 ++++++---- 4 files changed, 20 insertions(+), 12 deletions(-)
Signature · 1 line
2.24.0
Johan Hovold
maintainerPATCH 1/4 USB: atm: ueagle-atm: add missing endpoint check
Make sure that the interrupt interface has an endpoint before trying to access its endpoint descriptors to avoid dereferencing a NULL pointer.
The driver binds to the interrupt interface with interface number 0, but must not assume that this interface or its current alternate setting are the first entries in the corresponding configuration arrays.
--- drivers/usb/atm/ueagle-atm.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/usb/atm/ueagle-atm.c +12 -6
@@ -2124,10 +2124,11 @@ static void uea_intr(struct urb *urb)/* * Start the modem : init the data and start kernel thread */ -static int uea_boot (struct uea_softc *sc) +static int uea_boot (struct uea_softc *sc,struct usb_interface *intf) { -int ret, size;struct intr_pkt *intr; +int ret = -ENOMEM ; +int size;uea_enters (INS_TO_USBDEV (sc));
@@ -2152,6 +2153,11 @@ static int uea_boot(struct uea_softc *sc)if (UEA_CHIP_VERSION (sc) ==ADI930 )load_XILINX_firmware (sc); +if (intf->cur_altsetting->desc.bNumEndpoints <1 ) { + ret = -ENODEV ; + goto err0; + } + intr =kmalloc (size,GFP_KERNEL );if (!intr) goto err0;
@@ -2163,8 +2169,7 @@ static int uea_boot(struct uea_softc *sc)usb_fill_int_urb (sc->urb_int, sc->usb_dev,usb_rcvintpipe (sc->usb_dev,UEA_INTR_PIPE ), intr, size, uea_intr, sc, - sc->usb_dev->actconfig->interface[0 ]->altsetting[0 ]. - endpoint[0 ].desc.bInterval); + intf->cur_altsetting->endpoint[0 ].desc.bInterval); ret =usb_submit_urb (sc->urb_int,GFP_KERNEL );if (ret <0 ) {
@@ -2179,6 +2184,7 @@ static int uea_boot(struct uea_softc *sc) sc->kthread =kthread_create (uea_kthread, sc,"ueagle-atm" );if (IS_ERR (sc->kthread)) {uea_err (INS_TO_USBDEV (sc),"failed to create thread\n" ); + ret =PTR_ERR (sc->kthread); goto err2; }
@@ -2193,7 +2199,7 @@ static int uea_boot(struct uea_softc *sc)kfree (intr); err0:uea_leaves (INS_TO_USBDEV (sc)); -return -ENOMEM ; +return ret; }/*
@@ -2548,7 +2554,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, } } - ret =uea_boot (sc); + ret =uea_boot (sc, intf);if (ret <0 ) goto error;
Signature · 1 line
2.24.0
Johan Hovold
maintainerPATCH 2/4 USB: adutux: fix interface sanity check
In reply to Johan HovoldMake sure to use the current alternate setting when verifying the interface descriptors to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN() in usb_submit_urb() that kernels with panic_on_warn set would choke on.
--- drivers/usb/misc/adutux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/misc/adutux.c +1 -1
@@ -669,7 +669,7 @@ static int adu_probe(struct usb_interface *interface,init_waitqueue_head (&dev->read_wait);init_waitqueue_head (&dev->write_wait); - res =usb_find_common_endpoints_reverse (&interface->altsetting[0 ], + res =usb_find_common_endpoints_reverse (interface->cur_altsetting,NULL ,NULL , &dev->interrupt_in_endpoint, &dev->interrupt_out_endpoint);
Signature · 1 line
2.24.0
Johan Hovold
maintainerPATCH 3/4 USB: idmouse: fix interface sanity checks
In reply to Johan HovoldMake sure to use the current alternate setting when verifying the interface descriptors to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN() in usb_submit_urb() that kernels with panic_on_warn set would choke on.
--- drivers/usb/misc/idmouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/misc/idmouse.c +1 -1
@@ -322,7 +322,7 @@ static int idmouse_probe(struct usb_interface *interface,int result;/* check if we have gotten the data or the hid interface */ - iface_desc = &interface->altsetting[0 ]; + iface_desc = interface->cur_altsetting;if (iface_desc->desc.bInterfaceClass !=0x0A )return -ENODEV ;
Signature · 1 line
2.24.0
Johan Hovold
maintainerPATCH 4/4 USB: serial: io_edgeport: fix epic endpoint lookup
In reply to Johan HovoldMake sure to use the current alternate setting when looking up the endpoints on epic devices to avoid binding to an invalid interface.
Failing to do so could cause the driver to misbehave or trigger a WARN() in usb_submit_urb() that kernels with panic_on_warn set would choke on.
--- drivers/usb/serial/io_edgeport.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/usb/serial/io_edgeport.c +6 -4
@@ -2901,16 +2901,18 @@ static int edge_startup(struct usb_serial *serial) response =0 ;if (edge_serial->is_epic) { +struct usb_host_interface *alt; + + alt = serial->interface->cur_altsetting; +/* EPIC thing, set up our interrupt polling now and our read * urb, so that the device knows it really is connected. */ interrupt_in_found = bulk_in_found = bulk_out_found = false; -for (i =0 ; i < serial->interface->altsetting[0 ] - .desc.bNumEndpoints; ++i) { +for (i =0 ; i < alt->desc.bNumEndpoints; ++i) {struct usb_endpoint_descriptor *endpoint;int buffer_size; - endpoint = &serial->interface->altsetting[0 ]. - endpoint[i].desc; + endpoint = &alt->endpoint[i].desc; buffer_size =usb_endpoint_maxp (endpoint);if (!interrupt_in_found && (usb_endpoint_is_int_in (endpoint))) {
Signature · 1 line
2.24.0