Commit b41ecf9a authored by Stefano Panella's avatar Stefano Panella Committed by Greg Kroah-Hartman

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: default avatarDavid Vrabel <david.vrabel@csr.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 99b830aa
...@@ -200,35 +200,40 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, ...@@ -200,35 +200,40 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
{ {
int result, bytes, secd_size; int result, bytes, secd_size;
struct device *dev = &usb_dev->dev; struct device *dev = &usb_dev->dev;
struct usb_security_descriptor secd; struct usb_security_descriptor *secd;
const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL; const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL;
void *secd_buf;
const void *itr, *top; const void *itr, *top;
char buf[64]; char buf[64];
secd = kmalloc(sizeof(struct usb_security_descriptor), GFP_KERNEL);
if (secd == NULL) {
result = -ENOMEM;
goto out;
}
result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
0, &secd, sizeof(secd)); 0, secd, sizeof(struct usb_security_descriptor));
if (result < sizeof(secd)) { if (result < sizeof(secd)) {
dev_err(dev, "Can't read security descriptor or " dev_err(dev, "Can't read security descriptor or "
"not enough data: %d\n", result); "not enough data: %d\n", result);
goto error_secd; goto out;
} }
secd_size = le16_to_cpu(secd.wTotalLength); secd_size = le16_to_cpu(secd->wTotalLength);
secd_buf = kmalloc(secd_size, GFP_KERNEL); secd = krealloc(secd, secd_size, GFP_KERNEL);
if (secd_buf == NULL) { if (secd == NULL) {
dev_err(dev, "Can't allocate space for security descriptors\n"); dev_err(dev, "Can't allocate space for security descriptors\n");
goto error_secd_alloc; goto out;
} }
result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
0, secd_buf, secd_size); 0, secd, secd_size);
if (result < secd_size) { if (result < secd_size) {
dev_err(dev, "Can't read security descriptor or " dev_err(dev, "Can't read security descriptor or "
"not enough data: %d\n", result); "not enough data: %d\n", result);
goto error_secd_all; goto out;
} }
bytes = 0; bytes = 0;
itr = secd_buf + sizeof(secd); itr = &secd[1];
top = secd_buf + result; top = (void *)secd + result;
while (itr < top) { while (itr < top) {
etd = itr; etd = itr;
if (top - itr < sizeof(*etd)) { if (top - itr < sizeof(*etd)) {
...@@ -259,24 +264,16 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, ...@@ -259,24 +264,16 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
dev_err(dev, "WUSB device doesn't support CCM1 encryption, " dev_err(dev, "WUSB device doesn't support CCM1 encryption, "
"can't use!\n"); "can't use!\n");
result = -EINVAL; result = -EINVAL;
goto error_no_ccm1; goto out;
} }
wusb_dev->ccm1_etd = *ccm1_etd; wusb_dev->ccm1_etd = *ccm1_etd;
dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n", dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
buf, wusb_et_name(ccm1_etd->bEncryptionType), buf, wusb_et_name(ccm1_etd->bEncryptionType),
ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex); ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
result = 0; result = 0;
kfree(secd_buf);
out: out:
kfree(secd);
return result; return result;
error_no_ccm1:
error_secd_all:
kfree(secd_buf);
error_secd_alloc:
error_secd:
goto out;
} }
void wusb_dev_sec_rm(struct wusb_dev *wusb_dev) void wusb_dev_sec_rm(struct wusb_dev *wusb_dev)
......
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