aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2009-11-05 11:37:03 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:55:20 -0500
commit85e034fdff2af6befc55904f3ab9cc5aa31be8fe (patch)
tree6128ed2bcfd50c1dedcf3cb61e752266708fdef5 /drivers/usb
parent796c8c78801ebf1bdebddda06a43276355ff91eb (diff)
USB: Check results of dma_map_single
In map_urb_for_dma(), the DMA address returned by dma_map_single() is not checked to determine if it is legal. This lack of checking contributed to a problem with the libertas wireless driver (http://marc.info/?l=linux-wireless&m=125695331205062&w=2). The difficulty was not detected until the buffer was unmapped. By this time memory corruption had occurred. The situation is fixed by testing the returned DMA address, and returning -EAGAIN if the address is invalid. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hcd.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 34de475f016e..026ab2fe5c2d 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1275,13 +1275,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
1275 1275
1276 if (usb_endpoint_xfer_control(&urb->ep->desc) 1276 if (usb_endpoint_xfer_control(&urb->ep->desc)
1277 && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { 1277 && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
1278 if (hcd->self.uses_dma) 1278 if (hcd->self.uses_dma) {
1279 urb->setup_dma = dma_map_single( 1279 urb->setup_dma = dma_map_single(
1280 hcd->self.controller, 1280 hcd->self.controller,
1281 urb->setup_packet, 1281 urb->setup_packet,
1282 sizeof(struct usb_ctrlrequest), 1282 sizeof(struct usb_ctrlrequest),
1283 DMA_TO_DEVICE); 1283 DMA_TO_DEVICE);
1284 else if (hcd->driver->flags & HCD_LOCAL_MEM) 1284 if (dma_mapping_error(hcd->self.controller,
1285 urb->setup_dma))
1286 return -EAGAIN;
1287 } else if (hcd->driver->flags & HCD_LOCAL_MEM)
1285 ret = hcd_alloc_coherent( 1288 ret = hcd_alloc_coherent(
1286 urb->dev->bus, mem_flags, 1289 urb->dev->bus, mem_flags,
1287 &urb->setup_dma, 1290 &urb->setup_dma,
@@ -1293,13 +1296,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
1293 dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; 1296 dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
1294 if (ret == 0 && urb->transfer_buffer_length != 0 1297 if (ret == 0 && urb->transfer_buffer_length != 0
1295 && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { 1298 && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
1296 if (hcd->self.uses_dma) 1299 if (hcd->self.uses_dma) {
1297 urb->transfer_dma = dma_map_single ( 1300 urb->transfer_dma = dma_map_single (
1298 hcd->self.controller, 1301 hcd->self.controller,
1299 urb->transfer_buffer, 1302 urb->transfer_buffer,
1300 urb->transfer_buffer_length, 1303 urb->transfer_buffer_length,
1301 dir); 1304 dir);
1302 else if (hcd->driver->flags & HCD_LOCAL_MEM) { 1305 if (dma_mapping_error(hcd->self.controller,
1306 urb->transfer_dma))
1307 return -EAGAIN;
1308 } else if (hcd->driver->flags & HCD_LOCAL_MEM) {
1303 ret = hcd_alloc_coherent( 1309 ret = hcd_alloc_coherent(
1304 urb->dev->bus, mem_flags, 1310 urb->dev->bus, mem_flags,
1305 &urb->transfer_dma, 1311 &urb->transfer_dma,