From fddd9b5bd6a28251b891b312f368a0df9c2bdd99 Mon Sep 17 00:00:00 2001 From: Rohith Kollalsi Date: Thu, 6 Jan 2022 14:56:51 +0530 Subject: [PATCH] usb: u_qdss: Add proper error handling in case of mapping failure In case, if mapping of data_buffer or desc_buffer fails in usb_bam_alloc_buffer, iova of it could be corrupt and there is no error handling present for that failure. So qdss driver thinks that qdss_set_data_connection is successful and proceeds for ep_queue which can lead to usb controller accessing corrupt iova address outside the dma pool of usb. Fix this by adding proper error handling in case of data_buffer or desc_buffer mapping failure. Change-Id: Id15ab1f90be052ca0fac209dc619b2e740e1531a Signed-off-by: Rohith Kollalsi --- drivers/platform/msm/usb_bam.c | 24 ++++++++++++++++++++++-- drivers/usb/gadget/function/u_qdss.c | 11 ++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c index bce3fe6bf168..152d0b4263e9 100644 --- a/drivers/platform/msm/usb_bam.c +++ b/drivers/platform/msm/usb_bam.c @@ -334,9 +334,15 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect) memset_io(data_buf->base, 0, data_buf->size); data_buf->iova = dma_map_resource(dev, data_buf->phys_base, data_buf->size, DMA_BIDIRECTIONAL, 0); - if (dma_mapping_error(dev, data_buf->iova)) + if (dma_mapping_error(dev, data_buf->iova)) { log_event_err("%s(): oci_mem: err mapping data_buf\n", __func__); + iounmap(data_buf->base); + data_buf->base = NULL; + ret = -ENOMEM; + goto err_exit; + } + log_event_dbg("%s: data_buf:%s virt:%pK, phys:%lx, iova:%lx\n", __func__, dev_name(dev), data_buf->base, (unsigned long)data_buf->phys_base, data_buf->iova); @@ -348,7 +354,11 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect) if (!desc_buf->base) { log_event_err("%s: ioremap failed for desc fifo\n", __func__); + dma_unmap_resource(dev, data_buf->iova, + data_buf->size, + DMA_BIDIRECTIONAL, 0); iounmap(data_buf->base); + data_buf->base = NULL; ret = -ENOMEM; goto err_exit; } @@ -356,9 +366,19 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect) desc_buf->iova = dma_map_resource(dev, desc_buf->phys_base, desc_buf->size, DMA_BIDIRECTIONAL, 0); - if (dma_mapping_error(dev, desc_buf->iova)) + if (dma_mapping_error(dev, desc_buf->iova)) { log_event_err("%s(): oci_mem: err mapping desc_buf\n", __func__); + dma_unmap_resource(dev, data_buf->iova, + data_buf->size, + DMA_BIDIRECTIONAL, 0); + iounmap(data_buf->base); + data_buf->base = NULL; + iounmap(desc_buf->base); + desc_buf->base = NULL; + ret = -ENOMEM; + goto err_exit; + } log_event_dbg("%s: desc_buf:%s virt:%pK, phys:%lx, iova:%lx\n", __func__, dev_name(dev), desc_buf->base, diff --git a/drivers/usb/gadget/function/u_qdss.c b/drivers/usb/gadget/function/u_qdss.c index 5556ed2d992c..37cb678e0eef 100644 --- a/drivers/usb/gadget/function/u_qdss.c +++ b/drivers/usb/gadget/function/u_qdss.c @@ -78,7 +78,16 @@ int set_qdss_data_connection(struct f_qdss *qdss, int enable) return -ENOMEM; } - usb_bam_alloc_fifos(usb_bam_type, idx); + ret = usb_bam_alloc_fifos(usb_bam_type, idx); + if (ret) { + pr_err("%s: usb_bam_alloc_fifos failed(%d)\n", + __func__, ret); + dma_unmap_resource(dev->parent, bam_info.qdss_bam_iova, + bam_info.qdss_bam_size, + DMA_BIDIRECTIONAL, 0); + return ret; + } + bam_info.data_fifo = kzalloc(sizeof(struct sps_mem_buffer), GFP_KERNEL); if (!bam_info.data_fifo) {