MA-9165 fix kernel panic issue reported by some android stress test
authorRichard Liu <xuegang.liu@nxp.com>
Fri, 13 Jan 2017 09:12:19 +0000 (17:12 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:58:21 +0000 (14:58 -0500)
The issue can be reproduced when run some android stress test, such as
monkey test, usb camera long time recording, AndroidSurface.apk.
When the issue happen we always found some zero memory is tampered
to 1, and then some kernel panic happen.

Two changes to fix the issue:
1. Requires mutex-lock in when reference gctSIGNAL in gckOS_MapSignal,
   to fix concurrent issue. If the signal is already freed at this point,
   atomic_inc_return may change zero memory to 1 and cause memory corruption.

     if (atomic_inc_return(&signal->ref) <= 1)
     {
         /* The previous value is 0, it has been deleted. */
         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
     }
2. Refine gckOS_UserSignal in kernel code, do not need reference and dereference
   around gckOS_Signal.

Change-Id: Ib5970e86dbfbfd7d73f27a07d5e77a38c78a5fb6
Signed-off-by: Richard Liu <xuegang.liu@nxp.com>
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c

index 1e9f4ef..ba575cf 100644 (file)
@@ -5983,27 +5983,15 @@ gckOS_UserSignal(
     )
 {
     gceSTATUS status;
-    gctSIGNAL signal;
 
     gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
                    Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
 
-    /* Map the signal into kernel space. */
-    gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
-
     /* Signal. */
-    status = gckOS_Signal(Os, signal, gcvTRUE);
-
-    /* Unmap the signal */
-    gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
+    status = gckOS_Signal(Os, Signal, gcvTRUE);
 
     gcmkFOOTER();
     return status;
-
-OnError:
-    /* Return the status. */
-    gcmkFOOTER();
-    return status;
 }
 
 /*******************************************************************************
@@ -6193,6 +6181,8 @@ gckOS_MapSignal(
     gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
     gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
 
+    mutex_lock(&Os->signalMutex);
+
     gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
 
     if (atomic_inc_return(&signal->ref) <= 1)
@@ -6203,11 +6193,15 @@ gckOS_MapSignal(
 
     *MappedSignal = (gctSIGNAL) Signal;
 
+    mutex_unlock(&Os->signalMutex);
+
     /* Success. */
     gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
     return gcvSTATUS_OK;
 
 OnError:
+    mutex_unlock(&Os->signalMutex);
+
     gcmkFOOTER_NO();
     return status;
 }