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 | |
| 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>
| -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) |
