--- /dev/null
+From 2fae9e5a7babada041e2e161699ade2447a01989 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 19 Sep 2016 19:09:51 +0100
+Subject: usb: misc: legousbtower: Fix NULL pointer deference
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 2fae9e5a7babada041e2e161699ade2447a01989 upstream.
+
+This patch fixes a NULL pointer dereference caused by a race codition in
+the probe function of the legousbtower driver. It re-structures the
+probe function to only register the interface after successfully reading
+the board's firmware ID.
+
+The probe function does not deregister the usb interface after an error
+receiving the devices firmware ID. The device file registered
+(/dev/usb/legousbtower%d) may be read/written globally before the probe
+function returns. When tower_delete is called in the probe function
+(after an r/w has been initiated), core dev structures are deleted while
+the file operation functions are still running. If the 0 address is
+mappable on the machine, this vulnerability can be used to create a
+Local Priviege Escalation exploit via a write-what-where condition by
+remapping dev->interrupt_out_buffer in tower_write. A forged USB device
+and local program execution would be required for LPE. The USB device
+would have to delay the control message in tower_probe and accept
+the control urb in tower_open whilst guest code initiated a write to the
+device file as tower_delete is called from the error in tower_probe.
+
+This bug has existed since 2003. Patch tested by emulated device.
+
+Reported-by: James Patrick-Evans <james@jmp-e.com>
+Tested-by: James Patrick-Evans <james@jmp-e.com>
+Signed-off-by: James Patrick-Evans <james@jmp-e.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/misc/legousbtower.c | 35 +++++++++++++++++------------------
+ 1 file changed, 17 insertions(+), 18 deletions(-)
+
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -898,24 +898,6 @@ static int tower_probe (struct usb_inter
+ dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
+ dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
+
+- /* we can register the device now, as it is ready */
+- usb_set_intfdata (interface, dev);
+-
+- retval = usb_register_dev (interface, &tower_class);
+-
+- if (retval) {
+- /* something prevented us from registering this driver */
+- dev_err(idev, "Not able to get a minor for this device.\n");
+- usb_set_intfdata (interface, NULL);
+- goto error;
+- }
+- dev->minor = interface->minor;
+-
+- /* let the user know what node this device is now attached to */
+- dev_info(&interface->dev, "LEGO USB Tower #%d now attached to major "
+- "%d minor %d\n", (dev->minor - LEGO_USB_TOWER_MINOR_BASE),
+- USB_MAJOR, dev->minor);
+-
+ /* get the firmware version and log it */
+ result = usb_control_msg (udev,
+ usb_rcvctrlpipe(udev, 0),
+@@ -936,6 +918,23 @@ static int tower_probe (struct usb_inter
+ get_version_reply.minor,
+ le16_to_cpu(get_version_reply.build_no));
+
++ /* we can register the device now, as it is ready */
++ usb_set_intfdata (interface, dev);
++
++ retval = usb_register_dev (interface, &tower_class);
++
++ if (retval) {
++ /* something prevented us from registering this driver */
++ dev_err(idev, "Not able to get a minor for this device.\n");
++ usb_set_intfdata (interface, NULL);
++ goto error;
++ }
++ dev->minor = interface->minor;
++
++ /* let the user know what node this device is now attached to */
++ dev_info(&interface->dev, "LEGO USB Tower #%d now attached to major "
++ "%d minor %d\n", (dev->minor - LEGO_USB_TOWER_MINOR_BASE),
++ USB_MAJOR, dev->minor);
+
+ exit:
+ return retval;