| From 7eea4e1d36a9ce57523e245862acbaebaf73ab6d Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Wed, 25 Sep 2019 11:29:12 +0200 |
| Subject: [PATCH] USB: adutux: fix use-after-free on disconnect |
| |
| commit 44efc269db7929f6275a1fa927ef082e533ecde0 upstream. |
| |
| The driver was clearing its struct usb_device pointer, which it used as |
| an inverted disconnected flag, before deregistering the character device |
| and without serialising against racing release(). |
| |
| This could lead to a use-after-free if a racing release() callback |
| observes the cleared pointer and frees the driver data before |
| disconnect() is finished with it. |
| |
| This could also lead to NULL-pointer dereferences in a racing open(). |
| |
| Fixes: f08812d5eb8f ("USB: FIx locks and urb->status in adutux (updated)") |
| Cc: stable <stable@vger.kernel.org> # 2.6.24 |
| Reported-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com |
| Tested-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Link: https://lore.kernel.org/r/20190925092913.8608-1-johan@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c |
| index 9465fb95d70a..fef855354ee4 100644 |
| --- a/drivers/usb/misc/adutux.c |
| +++ b/drivers/usb/misc/adutux.c |
| @@ -764,14 +764,15 @@ static void adu_disconnect(struct usb_interface *interface) |
| |
| dev = usb_get_intfdata(interface); |
| |
| - mutex_lock(&dev->mtx); /* not interruptible */ |
| - dev->udev = NULL; /* poison */ |
| usb_deregister_dev(interface, &adu_class); |
| - mutex_unlock(&dev->mtx); |
| |
| mutex_lock(&adutux_mutex); |
| usb_set_intfdata(interface, NULL); |
| |
| + mutex_lock(&dev->mtx); /* not interruptible */ |
| + dev->udev = NULL; /* poison */ |
| + mutex_unlock(&dev->mtx); |
| + |
| /* if the device is not opened, then we clean up right now */ |
| if (!dev->open_count) |
| adu_delete(dev); |
| -- |
| 2.7.4 |
| |