diff options
author | Stefano Panella <stefano.panella@csr.com> | 2009-10-12 11:45:14 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-10-14 17:54:42 -0400 |
commit | b41ecf9a80a55406eb4bf90c1ba260785002e103 (patch) | |
tree | 069ffc368a0eb1b405f53b1adb7a6b41ff37ae94 /drivers | |
parent | 99b830aa553668a2c433e4cbff130224a75c74bb (diff) |
USB: wusb: don't use the stack to read security descriptor
An urb's transfer buffer must be kmalloc'd memory and not point to the
stack or a DMA API warning results.
Signed-off-by: David Vrabel <david.vrabel@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/wusbcore/security.c | 41 |
1 files changed, 19 insertions, 22 deletions
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index b2f149fedcc5..4516c36436e6 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c | |||
@@ -200,35 +200,40 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, | |||
200 | { | 200 | { |
201 | int result, bytes, secd_size; | 201 | int result, bytes, secd_size; |
202 | struct device *dev = &usb_dev->dev; | 202 | struct device *dev = &usb_dev->dev; |
203 | struct usb_security_descriptor secd; | 203 | struct usb_security_descriptor *secd; |
204 | const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL; | 204 | const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL; |
205 | void *secd_buf; | ||
206 | const void *itr, *top; | 205 | const void *itr, *top; |
207 | char buf[64]; | 206 | char buf[64]; |
208 | 207 | ||
208 | secd = kmalloc(sizeof(struct usb_security_descriptor), GFP_KERNEL); | ||
209 | if (secd == NULL) { | ||
210 | result = -ENOMEM; | ||
211 | goto out; | ||
212 | } | ||
213 | |||
209 | result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, | 214 | result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, |
210 | 0, &secd, sizeof(secd)); | 215 | 0, secd, sizeof(struct usb_security_descriptor)); |
211 | if (result < sizeof(secd)) { | 216 | if (result < sizeof(secd)) { |
212 | dev_err(dev, "Can't read security descriptor or " | 217 | dev_err(dev, "Can't read security descriptor or " |
213 | "not enough data: %d\n", result); | 218 | "not enough data: %d\n", result); |
214 | goto error_secd; | 219 | goto out; |
215 | } | 220 | } |
216 | secd_size = le16_to_cpu(secd.wTotalLength); | 221 | secd_size = le16_to_cpu(secd->wTotalLength); |
217 | secd_buf = kmalloc(secd_size, GFP_KERNEL); | 222 | secd = krealloc(secd, secd_size, GFP_KERNEL); |
218 | if (secd_buf == NULL) { | 223 | if (secd == NULL) { |
219 | dev_err(dev, "Can't allocate space for security descriptors\n"); | 224 | dev_err(dev, "Can't allocate space for security descriptors\n"); |
220 | goto error_secd_alloc; | 225 | goto out; |
221 | } | 226 | } |
222 | result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, | 227 | result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, |
223 | 0, secd_buf, secd_size); | 228 | 0, secd, secd_size); |
224 | if (result < secd_size) { | 229 | if (result < secd_size) { |
225 | dev_err(dev, "Can't read security descriptor or " | 230 | dev_err(dev, "Can't read security descriptor or " |
226 | "not enough data: %d\n", result); | 231 | "not enough data: %d\n", result); |
227 | goto error_secd_all; | 232 | goto out; |
228 | } | 233 | } |
229 | bytes = 0; | 234 | bytes = 0; |
230 | itr = secd_buf + sizeof(secd); | 235 | itr = &secd[1]; |
231 | top = secd_buf + result; | 236 | top = (void *)secd + result; |
232 | while (itr < top) { | 237 | while (itr < top) { |
233 | etd = itr; | 238 | etd = itr; |
234 | if (top - itr < sizeof(*etd)) { | 239 | if (top - itr < sizeof(*etd)) { |
@@ -259,24 +264,16 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, | |||
259 | dev_err(dev, "WUSB device doesn't support CCM1 encryption, " | 264 | dev_err(dev, "WUSB device doesn't support CCM1 encryption, " |
260 | "can't use!\n"); | 265 | "can't use!\n"); |
261 | result = -EINVAL; | 266 | result = -EINVAL; |
262 | goto error_no_ccm1; | 267 | goto out; |
263 | } | 268 | } |
264 | wusb_dev->ccm1_etd = *ccm1_etd; | 269 | wusb_dev->ccm1_etd = *ccm1_etd; |
265 | dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n", | 270 | dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n", |
266 | buf, wusb_et_name(ccm1_etd->bEncryptionType), | 271 | buf, wusb_et_name(ccm1_etd->bEncryptionType), |
267 | ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex); | 272 | ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex); |
268 | result = 0; | 273 | result = 0; |
269 | kfree(secd_buf); | ||
270 | out: | 274 | out: |
275 | kfree(secd); | ||
271 | return result; | 276 | return result; |
272 | |||
273 | |||
274 | error_no_ccm1: | ||
275 | error_secd_all: | ||
276 | kfree(secd_buf); | ||
277 | error_secd_alloc: | ||
278 | error_secd: | ||
279 | goto out; | ||
280 | } | 277 | } |
281 | 278 | ||
282 | void wusb_dev_sec_rm(struct wusb_dev *wusb_dev) | 279 | void wusb_dev_sec_rm(struct wusb_dev *wusb_dev) |