USB: fix bugs in usb_(de)authorize_device
This patch (as1315) fixes some bugs in the USB core authorization code: usb_deauthorize_device() should deallocate the device strings instead of leaking them, and it should invoke usb_destroy_configuration() (which does proper reference counting) instead of freeing the config information directly. usb_authorize_device() shouldn't change the device strings until it knows that the authorization will succeed, and it should autosuspend the device at the end (having autoresumed the device at the start). Because the device strings can be changed, the sysfs routines to display the strings must protect the string pointers by locking the device. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: Inaky Perez-Gonzalez <inaky@linux.intel.com> Acked-by: David Vrabel <david.vrabel@csr.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
8d8558d108
commit
da307123c6
|
@ -1849,21 +1849,23 @@ fail:
|
|||
*/
|
||||
int usb_deauthorize_device(struct usb_device *usb_dev)
|
||||
{
|
||||
unsigned cnt;
|
||||
usb_lock_device(usb_dev);
|
||||
if (usb_dev->authorized == 0)
|
||||
goto out_unauthorized;
|
||||
|
||||
usb_dev->authorized = 0;
|
||||
usb_set_configuration(usb_dev, -1);
|
||||
|
||||
kfree(usb_dev->product);
|
||||
usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
kfree(usb_dev->manufacturer);
|
||||
usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
kfree(usb_dev->serial);
|
||||
usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
kfree(usb_dev->config);
|
||||
usb_dev->config = NULL;
|
||||
for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++)
|
||||
kfree(usb_dev->rawdescriptors[cnt]);
|
||||
|
||||
usb_destroy_configuration(usb_dev);
|
||||
usb_dev->descriptor.bNumConfigurations = 0;
|
||||
kfree(usb_dev->rawdescriptors);
|
||||
|
||||
out_unauthorized:
|
||||
usb_unlock_device(usb_dev);
|
||||
return 0;
|
||||
|
@ -1873,15 +1875,11 @@ out_unauthorized:
|
|||
int usb_authorize_device(struct usb_device *usb_dev)
|
||||
{
|
||||
int result = 0, c;
|
||||
|
||||
usb_lock_device(usb_dev);
|
||||
if (usb_dev->authorized == 1)
|
||||
goto out_authorized;
|
||||
kfree(usb_dev->product);
|
||||
usb_dev->product = NULL;
|
||||
kfree(usb_dev->manufacturer);
|
||||
usb_dev->manufacturer = NULL;
|
||||
kfree(usb_dev->serial);
|
||||
usb_dev->serial = NULL;
|
||||
|
||||
result = usb_autoresume_device(usb_dev);
|
||||
if (result < 0) {
|
||||
dev_err(&usb_dev->dev,
|
||||
|
@ -1894,6 +1892,14 @@ int usb_authorize_device(struct usb_device *usb_dev)
|
|||
"authorization: %d\n", result);
|
||||
goto error_device_descriptor;
|
||||
}
|
||||
|
||||
kfree(usb_dev->product);
|
||||
usb_dev->product = NULL;
|
||||
kfree(usb_dev->manufacturer);
|
||||
usb_dev->manufacturer = NULL;
|
||||
kfree(usb_dev->serial);
|
||||
usb_dev->serial = NULL;
|
||||
|
||||
usb_dev->authorized = 1;
|
||||
result = usb_enumerate_device(usb_dev);
|
||||
if (result < 0)
|
||||
|
@ -1912,8 +1918,10 @@ int usb_authorize_device(struct usb_device *usb_dev)
|
|||
}
|
||||
}
|
||||
dev_info(&usb_dev->dev, "authorized to connect\n");
|
||||
|
||||
error_enumerate:
|
||||
error_device_descriptor:
|
||||
usb_autosuspend_device(usb_dev);
|
||||
error_autoresume:
|
||||
out_authorized:
|
||||
usb_unlock_device(usb_dev); // complements locktree
|
||||
|
|
|
@ -82,9 +82,13 @@ static ssize_t show_##name(struct device *dev, \
|
|||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct usb_device *udev; \
|
||||
int retval; \
|
||||
\
|
||||
udev = to_usb_device(dev); \
|
||||
return sprintf(buf, "%s\n", udev->name); \
|
||||
usb_lock_device(udev); \
|
||||
retval = sprintf(buf, "%s\n", udev->name); \
|
||||
usb_unlock_device(udev); \
|
||||
return retval; \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
|
||||
|
||||
|
|
Loading…
Reference in New Issue