[PATCH] DSPBRIDGE: Prevent memory corruption in DRV_ProcFreeDMMRes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Background: bridge_close() has the responsibility to cleanup all the
resources allocated by user space process. One of those resources is
DMMRes which is used for tracking DMM resource allocation done in
PROC_Map() and PROC_UnMap().

DRV_ProcFreeDMMRes() function was used for cleaning up DMMRes has following
problems which are fixed by this patch:

1. It access and modifies pDMMRes pointer when it is already freed by
PROC_UnMap()
2. Instead of passing ulDSPAddr it passes ulDSPResAddr to PROC_UnMap() which
will not retrive correct DMMRes element.

CC: Omar Ramirez Luna <omar.ramirez@xxxxxx>
CC: Nishanth Menon <nm@xxxxxx>
CC: Deepak Chitriki Rudramuni <deepak.chitriki@xxxxxx>
CC: Felipe Contreras <felipe.contreras@xxxxxxxxx>
CC: Phil Carmody <ext-phil.2.carmody@xxxxxxxxx>

Signed-off-by: Ameya Palande <ameya.palande@xxxxxxxxx>
---
 arch/arm/plat-omap/include/dspbridge/drv.h         |   14 ----
 .../plat-omap/include/dspbridge/resourcecleanup.h  |    4 +-
 drivers/dsp/bridge/rmgr/drv.c                      |   63 ++++++++------------
 drivers/dsp/bridge/rmgr/drv_interface.c            |    7 +-
 4 files changed, 30 insertions(+), 58 deletions(-)

diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h
index b6a5fd2..ba11359 100644
--- a/arch/arm/plat-omap/include/dspbridge/drv.h
+++ b/arch/arm/plat-omap/include/dspbridge/drv.h
@@ -384,18 +384,4 @@ struct PROCESS_CONTEXT{
  */
 	extern DSP_STATUS DRV_ReleaseResources(IN u32 dwContext,
 					       struct DRV_OBJECT *hDrvObject);
-
-/*
- *  ======== DRV_ProcFreeDMMRes ========
- *  Purpose:
- *       Actual DMM De-Allocation.
- *  Parameters:
- *      hPCtxt:      Path to the driver Registry Key.
- *  Returns:
- *      DSP_SOK if success;
- */
-
-
-	extern DSP_STATUS  DRV_ProcFreeDMMRes(HANDLE hPCtxt);
-
 #endif				/* DRV_ */
diff --git a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
index ffbcf5e..d399a2e 100644
--- a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+++ b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
@@ -25,13 +25,13 @@ extern DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
 extern DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject,
 					HANDLE hPCtxt);
 
-extern DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE pCtxt);
+extern DSP_STATUS DRV_Remove_All_DMM_Res_Elements(HANDLE hPCtxt);
 
 extern DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE pCtxt);
 
 extern DSP_STATUS DRV_ProcSetPID(HANDLE pCtxt, s32 hProcess);
 
-extern DSP_STATUS DRV_RemoveAllResources(HANDLE pPctxt);
+extern void DRV_RemoveAllResources(HANDLE pPctxt);
 
 extern DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
 				     HANDLE pr_ctxt);
diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c
index eca46ca..570f8a4 100644
--- a/drivers/dsp/bridge/rmgr/drv.c
+++ b/drivers/dsp/bridge/rmgr/drv.c
@@ -259,52 +259,39 @@ DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
 	return status;
 }
 
-/* Actual DMM De-Allocation */
-DSP_STATUS  DRV_ProcFreeDMMRes(HANDLE hPCtxt)
+/* Release all DMM resources and its context */
+DSP_STATUS DRV_Remove_All_DMM_Res_Elements(HANDLE hPCtxt)
 {
-	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	struct PROCESS_CONTEXT *p_ctxt = (struct PROCESS_CONTEXT *)hPCtxt;
 	DSP_STATUS status = DSP_SOK;
-	struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
-	struct DMM_RES_OBJECT *pDMMRes = NULL;
-
-	GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
-	while (pDMMList != NULL) {
-		pDMMRes = pDMMList;
-		pDMMList = pDMMList->next;
-		if (pDMMRes->dmmAllocated) {
-			status = PROC_UnMap(pDMMRes->hProcessor,
-				 (void *)pDMMRes->ulDSPResAddr, pCtxt);
+	struct DMM_RES_OBJECT *p_dmm_list = p_ctxt->pDMMList;
+	struct DMM_RES_OBJECT *p_cur_res;
+
+	while (p_dmm_list) {
+		p_cur_res = p_dmm_list;
+		p_dmm_list = p_dmm_list->next;
+		if (p_cur_res->dmmAllocated) {
+			/*
+			 * PROC_UnMap will free memory allocated to p_cur_res
+			 * pointer. So we need to save following data for the
+			 * execution of PROC_UnReserveMemory()
+			 */
+			void *h_processor = p_cur_res->hProcessor;
+			u32 dsp_res_addr = p_cur_res->ulDSPResAddr;
+
+			status = PROC_UnMap(p_cur_res->hProcessor,
+				 (void *)p_cur_res->ulDSPAddr, p_ctxt);
 			if (DSP_FAILED(status))
 				pr_debug("%s: PROC_UnMap failed! status ="
-						" 0x%xn", __func__, status);
-			status = PROC_UnReserveMemory(pDMMRes->hProcessor,
-				 (void *)pDMMRes->ulDSPResAddr);
+						" 0x%x\n", __func__, status);
+			status = PROC_UnReserveMemory(h_processor,
+				 (void *)dsp_res_addr);
 			if (DSP_FAILED(status))
 				pr_debug("%s: PROC_UnReserveMemory failed!"
-					" status = 0x%xn", __func__, status);
-			pDMMRes->dmmAllocated = 0;
+					" status = 0x%x\n", __func__, status);
 		}
 	}
-	return status;
-}
-
-/* Release all DMM resources and its context
-* This is called from .bridge_release. */
-DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
-{
-	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
-	DSP_STATUS status = DSP_SOK;
-	struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
-	struct DMM_RES_OBJECT *pTempDMMRes = NULL;
-
-	DRV_ProcFreeDMMRes(pCtxt);
-	pTempDMMRes = pCtxt->pDMMList;
-	while (pTempDMMRes != NULL) {
-		pTempDMMRes2 = pTempDMMRes;
-		pTempDMMRes = pTempDMMRes->next;
-		MEM_Free(pTempDMMRes2);
-	}
-	pCtxt->pDMMList = NULL;
+	p_ctxt->pDMMList = NULL;
 	return status;
 }
 
diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
index 625f88e..2e56704 100644
--- a/drivers/dsp/bridge/rmgr/drv_interface.c
+++ b/drivers/dsp/bridge/rmgr/drv_interface.c
@@ -604,15 +604,14 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
 
 /* To remove all process resources before removing the process from the
  * process context list*/
-DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
+void DRV_RemoveAllResources(HANDLE hPCtxt)
 {
-	DSP_STATUS status = DSP_SOK;
 	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
 	DRV_RemoveAllSTRMResElements(pCtxt);
 	DRV_RemoveAllNodeResElements(pCtxt);
-	DRV_RemoveAllDMMResElements(pCtxt);
+	DRV_Remove_All_DMM_Res_Elements(pCtxt);
 	pCtxt->resState = PROC_RES_FREED;
-	return status;
+	return;
 }
 
 /* Bridge driver initialization and de-initialization functions */
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux