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>
This commit is contained in:
Родитель
796c8c7880
Коммит
85e034fdff
|
@ -1275,13 +1275,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
|||
|
||||
if (usb_endpoint_xfer_control(&urb->ep->desc)
|
||||
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
|
||||
if (hcd->self.uses_dma)
|
||||
if (hcd->self.uses_dma) {
|
||||
urb->setup_dma = dma_map_single(
|
||||
hcd->self.controller,
|
||||
urb->setup_packet,
|
||||
sizeof(struct usb_ctrlrequest),
|
||||
DMA_TO_DEVICE);
|
||||
else if (hcd->driver->flags & HCD_LOCAL_MEM)
|
||||
if (dma_mapping_error(hcd->self.controller,
|
||||
urb->setup_dma))
|
||||
return -EAGAIN;
|
||||
} else if (hcd->driver->flags & HCD_LOCAL_MEM)
|
||||
ret = hcd_alloc_coherent(
|
||||
urb->dev->bus, mem_flags,
|
||||
&urb->setup_dma,
|
||||
|
@ -1293,13 +1296,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
|||
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
|
||||
if (ret == 0 && urb->transfer_buffer_length != 0
|
||||
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
|
||||
if (hcd->self.uses_dma)
|
||||
if (hcd->self.uses_dma) {
|
||||
urb->transfer_dma = dma_map_single (
|
||||
hcd->self.controller,
|
||||
urb->transfer_buffer,
|
||||
urb->transfer_buffer_length,
|
||||
dir);
|
||||
else if (hcd->driver->flags & HCD_LOCAL_MEM) {
|
||||
if (dma_mapping_error(hcd->self.controller,
|
||||
urb->transfer_dma))
|
||||
return -EAGAIN;
|
||||
} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
|
||||
ret = hcd_alloc_coherent(
|
||||
urb->dev->bus, mem_flags,
|
||||
&urb->transfer_dma,
|
||||
|
|
Загрузка…
Ссылка в новой задаче