]>
Commit | Line | Data |
---|---|---|
80e6ae8f GKH |
1 | From da307123c621b01cce147a4be313d8a754674f63 Mon Sep 17 00:00:00 2001 |
2 | From: Alan Stern <stern@rowland.harvard.edu> | |
3 | Date: Tue, 8 Dec 2009 15:54:44 -0500 | |
4 | Subject: USB: fix bugs in usb_(de)authorize_device | |
5 | ||
6 | From: Alan Stern <stern@rowland.harvard.edu> | |
7 | ||
8 | commit da307123c621b01cce147a4be313d8a754674f63 upstream. | |
9 | ||
10 | This patch (as1315) fixes some bugs in the USB core authorization | |
11 | code: | |
12 | ||
13 | usb_deauthorize_device() should deallocate the device strings | |
14 | instead of leaking them, and it should invoke | |
15 | usb_destroy_configuration() (which does proper reference | |
16 | counting) instead of freeing the config information directly. | |
17 | ||
18 | usb_authorize_device() shouldn't change the device strings | |
19 | until it knows that the authorization will succeed, and it should | |
20 | autosuspend the device at the end (having autoresumed the | |
21 | device at the start). | |
22 | ||
23 | Because the device strings can be changed, the sysfs routines | |
24 | to display the strings must protect the string pointers by | |
25 | locking the device. | |
26 | ||
27 | Signed-off-by: Alan Stern <stern@rowland.harvard.edu> | |
28 | CC: Inaky Perez-Gonzalez <inaky@linux.intel.com> | |
29 | Acked-by: David Vrabel <david.vrabel@csr.com> | |
30 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
31 | ||
32 | --- | |
33 | drivers/usb/core/hub.c | 32 ++++++++++++++++++++------------ | |
34 | drivers/usb/core/sysfs.c | 6 +++++- | |
35 | 2 files changed, 25 insertions(+), 13 deletions(-) | |
36 | ||
37 | --- a/drivers/usb/core/hub.c | |
38 | +++ b/drivers/usb/core/hub.c | |
39 | @@ -1803,21 +1803,23 @@ fail: | |
40 | */ | |
41 | int usb_deauthorize_device(struct usb_device *usb_dev) | |
42 | { | |
43 | - unsigned cnt; | |
44 | usb_lock_device(usb_dev); | |
45 | if (usb_dev->authorized == 0) | |
46 | goto out_unauthorized; | |
47 | + | |
48 | usb_dev->authorized = 0; | |
49 | usb_set_configuration(usb_dev, -1); | |
50 | + | |
51 | + kfree(usb_dev->product); | |
52 | usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); | |
53 | + kfree(usb_dev->manufacturer); | |
54 | usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); | |
55 | + kfree(usb_dev->serial); | |
56 | usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); | |
57 | - kfree(usb_dev->config); | |
58 | - usb_dev->config = NULL; | |
59 | - for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++) | |
60 | - kfree(usb_dev->rawdescriptors[cnt]); | |
61 | + | |
62 | + usb_destroy_configuration(usb_dev); | |
63 | usb_dev->descriptor.bNumConfigurations = 0; | |
64 | - kfree(usb_dev->rawdescriptors); | |
65 | + | |
66 | out_unauthorized: | |
67 | usb_unlock_device(usb_dev); | |
68 | return 0; | |
69 | @@ -1827,15 +1829,11 @@ out_unauthorized: | |
70 | int usb_authorize_device(struct usb_device *usb_dev) | |
71 | { | |
72 | int result = 0, c; | |
73 | + | |
74 | usb_lock_device(usb_dev); | |
75 | if (usb_dev->authorized == 1) | |
76 | goto out_authorized; | |
77 | - kfree(usb_dev->product); | |
78 | - usb_dev->product = NULL; | |
79 | - kfree(usb_dev->manufacturer); | |
80 | - usb_dev->manufacturer = NULL; | |
81 | - kfree(usb_dev->serial); | |
82 | - usb_dev->serial = NULL; | |
83 | + | |
84 | result = usb_autoresume_device(usb_dev); | |
85 | if (result < 0) { | |
86 | dev_err(&usb_dev->dev, | |
87 | @@ -1848,6 +1846,14 @@ int usb_authorize_device(struct usb_devi | |
88 | "authorization: %d\n", result); | |
89 | goto error_device_descriptor; | |
90 | } | |
91 | + | |
92 | + kfree(usb_dev->product); | |
93 | + usb_dev->product = NULL; | |
94 | + kfree(usb_dev->manufacturer); | |
95 | + usb_dev->manufacturer = NULL; | |
96 | + kfree(usb_dev->serial); | |
97 | + usb_dev->serial = NULL; | |
98 | + | |
99 | usb_dev->authorized = 1; | |
100 | result = usb_enumerate_device(usb_dev); | |
101 | if (result < 0) | |
102 | @@ -1866,8 +1872,10 @@ int usb_authorize_device(struct usb_devi | |
103 | } | |
104 | } | |
105 | dev_info(&usb_dev->dev, "authorized to connect\n"); | |
106 | + | |
107 | error_enumerate: | |
108 | error_device_descriptor: | |
109 | + usb_autosuspend_device(usb_dev); | |
110 | error_autoresume: | |
111 | out_authorized: | |
112 | usb_unlock_device(usb_dev); // complements locktree | |
113 | --- a/drivers/usb/core/sysfs.c | |
114 | +++ b/drivers/usb/core/sysfs.c | |
115 | @@ -82,9 +82,13 @@ static ssize_t show_##name(struct devic | |
116 | struct device_attribute *attr, char *buf) \ | |
117 | { \ | |
118 | struct usb_device *udev; \ | |
119 | + int retval; \ | |
120 | \ | |
121 | udev = to_usb_device(dev); \ | |
122 | - return sprintf(buf, "%s\n", udev->name); \ | |
123 | + usb_lock_device(udev); \ | |
124 | + retval = sprintf(buf, "%s\n", udev->name); \ | |
125 | + usb_unlock_device(udev); \ | |
126 | + return retval; \ | |
127 | } \ | |
128 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); | |
129 |