summaryrefslogtreecommitdiff
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.com>2019-08-08 16:21:19 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-08-25 10:53:02 +0200
commit8fed007578dba671e131781360dd87c4683672e7 (patch)
treeca063014dc613dc6220bf87a370f2ec22d0e0ccb /drivers/usb/class/cdc-acm.c
parent8f67bc7c8da8622fddf4d29a2f422678dfbadf77 (diff)
usb: cdc-acm: make sure a refcount is taken early enough
commit c52873e5a1ef72f845526d9f6a50704433f9c625 upstream. destroy() will decrement the refcount on the interface, so that it needs to be taken so early that it never undercounts. Fixes: 7fb57a019f94e ("USB: cdc-acm: Fix potential deadlock (lockdep warning)") Cc: stable <stable@vger.kernel.org> Reported-and-tested-by: syzbot+1b2449b7b5dc240d107a@syzkaller.appspotmail.com Signed-off-by: Oliver Neukum <oneukum@suse.com> Link: https://lore.kernel.org/r/20190808142119.7998-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 736de1021d8b..1930a8ec4b67 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1319,13 +1319,6 @@ made_compressed_probe:
if (acm == NULL)
goto alloc_fail;
- minor = acm_alloc_minor(acm);
- if (minor < 0) {
- dev_err(&intf->dev, "no more free acm devices\n");
- kfree(acm);
- return -ENODEV;
- }
-
ctrlsize = usb_endpoint_maxp(epctrl);
readsize = usb_endpoint_maxp(epread) *
(quirks == SINGLE_RX_URB ? 1 : 2);
@@ -1333,6 +1326,16 @@ made_compressed_probe:
acm->writesize = usb_endpoint_maxp(epwrite) * 20;
acm->control = control_interface;
acm->data = data_interface;
+
+ usb_get_intf(acm->control); /* undone in destruct() */
+
+ minor = acm_alloc_minor(acm);
+ if (minor < 0) {
+ dev_err(&intf->dev, "no more free acm devices\n");
+ kfree(acm);
+ return -ENODEV;
+ }
+
acm->minor = minor;
acm->dev = usb_dev;
acm->ctrl_caps = ac_management_function;
@@ -1474,7 +1477,6 @@ skip_countries:
usb_driver_claim_interface(&acm_driver, data_interface, acm);
usb_set_intfdata(data_interface, acm);
- usb_get_intf(control_interface);
tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
&control_interface->dev);
if (IS_ERR(tty_dev)) {