Commit d92a3ca6 authored by Ming Lei's avatar Ming Lei Committed by Greg Kroah-Hartman

USB: serial: fix leak of usb serial module refrence count

The patch with title below makes reference count of usb serial module
always more than one after driver is bound.

	USB-BKL: Remove BKL use for usb serial driver probing

In fact, the patch above only replaces lock_kernel() with try_module_get()
, and does not use module_put() to do what unlock_kernel() did, so casue leak
of reference count of usb serial module and the module can not be unloaded
after serial driver is bound with device.

This patch fixes the issue, also simplifies such things:
	-only call try_module_get() once in the entry of usb_serial_probe()
	-only call module_put() once in the exit of usb_serial_probe
Signed-off-by: default avatarMing Lei <tom.leiming@gmail.com>
Cc: Johan Hovold <jhovold@gmail.com>
Cc: Andi Kleen <ak@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 0eee6a2b
...@@ -736,6 +736,7 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -736,6 +736,7 @@ int usb_serial_probe(struct usb_interface *interface,
serial = create_serial(dev, interface, type); serial = create_serial(dev, interface, type);
if (!serial) { if (!serial) {
module_put(type->driver.owner);
dev_err(&interface->dev, "%s - out of memory\n", __func__); dev_err(&interface->dev, "%s - out of memory\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
...@@ -746,11 +747,11 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -746,11 +747,11 @@ int usb_serial_probe(struct usb_interface *interface,
id = get_iface_id(type, interface); id = get_iface_id(type, interface);
retval = type->probe(serial, id); retval = type->probe(serial, id);
module_put(type->driver.owner);
if (retval) { if (retval) {
dbg("sub driver rejected device"); dbg("sub driver rejected device");
kfree(serial); kfree(serial);
module_put(type->driver.owner);
return retval; return retval;
} }
} }
...@@ -822,6 +823,7 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -822,6 +823,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (num_bulk_in == 0 || num_bulk_out == 0) { if (num_bulk_in == 0 || num_bulk_out == 0) {
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
kfree(serial); kfree(serial);
module_put(type->driver.owner);
return -ENODEV; return -ENODEV;
} }
} }
...@@ -835,22 +837,15 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -835,22 +837,15 @@ int usb_serial_probe(struct usb_interface *interface,
dev_err(&interface->dev, dev_err(&interface->dev,
"Generic device with no bulk out, not allowed.\n"); "Generic device with no bulk out, not allowed.\n");
kfree(serial); kfree(serial);
module_put(type->driver.owner);
return -EIO; return -EIO;
} }
} }
#endif #endif
if (!num_ports) { if (!num_ports) {
/* if this device type has a calc_num_ports function, call it */ /* if this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) { if (type->calc_num_ports)
if (!try_module_get(type->driver.owner)) {
dev_err(&interface->dev,
"module get failed, exiting\n");
kfree(serial);
return -EIO;
}
num_ports = type->calc_num_ports(serial); num_ports = type->calc_num_ports(serial);
module_put(type->driver.owner);
}
if (!num_ports) if (!num_ports)
num_ports = type->num_ports; num_ports = type->num_ports;
} }
...@@ -1039,13 +1034,7 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -1039,13 +1034,7 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has an attach function, call it */ /* if this device type has an attach function, call it */
if (type->attach) { if (type->attach) {
if (!try_module_get(type->driver.owner)) {
dev_err(&interface->dev,
"module get failed, exiting\n");
goto probe_error;
}
retval = type->attach(serial); retval = type->attach(serial);
module_put(type->driver.owner);
if (retval < 0) if (retval < 0)
goto probe_error; goto probe_error;
serial->attached = 1; serial->attached = 1;
...@@ -1088,10 +1077,12 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -1088,10 +1077,12 @@ int usb_serial_probe(struct usb_interface *interface,
exit: exit:
/* success */ /* success */
usb_set_intfdata(interface, serial); usb_set_intfdata(interface, serial);
module_put(type->driver.owner);
return 0; return 0;
probe_error: probe_error:
usb_serial_put(serial); usb_serial_put(serial);
module_put(type->driver.owner);
return -EIO; return -EIO;
} }
EXPORT_SYMBOL_GPL(usb_serial_probe); EXPORT_SYMBOL_GPL(usb_serial_probe);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment