Allow start scheduler and free context SVC from privileged code only (#1475)

Allow start scheduler and free context SVC from privileged code only

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
diff --git a/portable/ARMv8M/non_secure/port.c b/portable/ARMv8M/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/ARMv8M/non_secure/port.c
+++ b/portable/ARMv8M/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/ARMv8M/secure/context/secure_context.c b/portable/ARMv8M/secure/context/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/ARMv8M/secure/context/secure_context.c
+++ b/portable/ARMv8M/secure/context/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_CM23/non_secure/port.c b/portable/GCC/ARM_CM23/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM23/non_secure/port.c
+++ b/portable/GCC/ARM_CM23/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM23/secure/secure_context.c b/portable/GCC/ARM_CM23/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/GCC/ARM_CM23/secure/secure_context.c
+++ b/portable/GCC/ARM_CM23/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c
+++ b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM33/non_secure/port.c b/portable/GCC/ARM_CM33/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM33/non_secure/port.c
+++ b/portable/GCC/ARM_CM33/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM33/secure/secure_context.c b/portable/GCC/ARM_CM33/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/GCC/ARM_CM33/secure/secure_context.c
+++ b/portable/GCC/ARM_CM33/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c
+++ b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM35P/non_secure/port.c b/portable/GCC/ARM_CM35P/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM35P/non_secure/port.c
+++ b/portable/GCC/ARM_CM35P/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM35P/secure/secure_context.c b/portable/GCC/ARM_CM35P/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/GCC/ARM_CM35P/secure/secure_context.c
+++ b/portable/GCC/ARM_CM35P/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c
+++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM52/non_secure/port.c b/portable/GCC/ARM_CM52/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM52/non_secure/port.c
+++ b/portable/GCC/ARM_CM52/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM52/secure/secure_context.c b/portable/GCC/ARM_CM52/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/GCC/ARM_CM52/secure/secure_context.c
+++ b/portable/GCC/ARM_CM52/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_CM52_NTZ/non_secure/port.c b/portable/GCC/ARM_CM52_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM52_NTZ/non_secure/port.c
+++ b/portable/GCC/ARM_CM52_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM55/non_secure/port.c b/portable/GCC/ARM_CM55/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM55/non_secure/port.c
+++ b/portable/GCC/ARM_CM55/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM55/secure/secure_context.c b/portable/GCC/ARM_CM55/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/GCC/ARM_CM55/secure/secure_context.c
+++ b/portable/GCC/ARM_CM55/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c
+++ b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM85/non_secure/port.c b/portable/GCC/ARM_CM85/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM85/non_secure/port.c
+++ b/portable/GCC/ARM_CM85/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_CM85/secure/secure_context.c b/portable/GCC/ARM_CM85/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/GCC/ARM_CM85/secure/secure_context.c
+++ b/portable/GCC/ARM_CM85/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c
+++ b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_STAR_MC3/non_secure/port.c b/portable/GCC/ARM_STAR_MC3/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_STAR_MC3/non_secure/port.c
+++ b/portable/GCC/ARM_STAR_MC3/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/GCC/ARM_STAR_MC3/secure/secure_context.c b/portable/GCC/ARM_STAR_MC3/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/GCC/ARM_STAR_MC3/secure/secure_context.c
+++ b/portable/GCC/ARM_STAR_MC3/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c b/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c
+++ b/portable/GCC/ARM_STAR_MC3_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM23/non_secure/port.c b/portable/IAR/ARM_CM23/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM23/non_secure/port.c
+++ b/portable/IAR/ARM_CM23/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM23/secure/secure_context.c b/portable/IAR/ARM_CM23/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/IAR/ARM_CM23/secure/secure_context.c
+++ b/portable/IAR/ARM_CM23/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c
+++ b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM33/non_secure/port.c b/portable/IAR/ARM_CM33/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM33/non_secure/port.c
+++ b/portable/IAR/ARM_CM33/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM33/secure/secure_context.c b/portable/IAR/ARM_CM33/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/IAR/ARM_CM33/secure/secure_context.c
+++ b/portable/IAR/ARM_CM33/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c
+++ b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM35P/non_secure/port.c b/portable/IAR/ARM_CM35P/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM35P/non_secure/port.c
+++ b/portable/IAR/ARM_CM35P/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM35P/secure/secure_context.c b/portable/IAR/ARM_CM35P/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/IAR/ARM_CM35P/secure/secure_context.c
+++ b/portable/IAR/ARM_CM35P/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c
+++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM52/non_secure/port.c b/portable/IAR/ARM_CM52/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM52/non_secure/port.c
+++ b/portable/IAR/ARM_CM52/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM52/secure/secure_context.c b/portable/IAR/ARM_CM52/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/IAR/ARM_CM52/secure/secure_context.c
+++ b/portable/IAR/ARM_CM52/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/IAR/ARM_CM52_NTZ/non_secure/port.c b/portable/IAR/ARM_CM52_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM52_NTZ/non_secure/port.c
+++ b/portable/IAR/ARM_CM52_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM55/non_secure/port.c b/portable/IAR/ARM_CM55/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM55/non_secure/port.c
+++ b/portable/IAR/ARM_CM55/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM55/secure/secure_context.c b/portable/IAR/ARM_CM55/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/IAR/ARM_CM55/secure/secure_context.c
+++ b/portable/IAR/ARM_CM55/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c
+++ b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM85/non_secure/port.c b/portable/IAR/ARM_CM85/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM85/non_secure/port.c
+++ b/portable/IAR/ARM_CM85/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_CM85/secure/secure_context.c b/portable/IAR/ARM_CM85/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/IAR/ARM_CM85/secure/secure_context.c
+++ b/portable/IAR/ARM_CM85/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c
+++ b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_STAR_MC3/non_secure/port.c b/portable/IAR/ARM_STAR_MC3/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_STAR_MC3/non_secure/port.c
+++ b/portable/IAR/ARM_STAR_MC3/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
diff --git a/portable/IAR/ARM_STAR_MC3/secure/secure_context.c b/portable/IAR/ARM_STAR_MC3/secure/secure_context.c
index 5e6ae3f..daf0d94 100644
--- a/portable/IAR/ARM_STAR_MC3/secure/secure_context.c
+++ b/portable/IAR/ARM_STAR_MC3/secure/secure_context.c
@@ -290,9 +290,12 @@
                                                               void * pvTaskHandle )
 {
     uint32_t ulIPSR, ulSecureContextIndex;
+    uint8_t * pucStackLimit;
 
-    /* Read the Interrupt Program Status Register (IPSR) value. */
+    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
+     * Register (PSPLIM) value. */
     secureportREAD_IPSR( ulIPSR );
+    secureportREAD_PSPLIM( pucStackLimit );
 
     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
      * when the processor is running in the Thread Mode. */
@@ -304,8 +307,14 @@
             ulSecureContextIndex = xSecureContextHandle - 1UL;
 
             /* Ensure that the secure context being deleted is associated with
-             * the task. */
-            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
+             * the task and is NOT the currently-loaded context. Freeing a
+             * context whose stack is currently loaded in PSPLIM would leave the
+             * running task referencing freed secure memory (use-after-free).
+             * pvTaskHandle is supplied by the non-secure side and is untrusted,
+             * so it is used only as an additional ownership match, not as
+             * authority. */
+            if( ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) &&
+                ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit != pucStackLimit ) )
             {
                 /* Free the stack space. */
                 vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
diff --git a/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c b/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c
index 2bb4c1d..9c3794c 100644
--- a/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c
+++ b/portable/IAR/ARM_STAR_MC3_NTZ/non_secure/port.c
@@ -1109,7 +1109,6 @@
 {
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
         #if defined( __ARMCC_VERSION )
-
             /* Declaration when these variable are defined in code instead of being
              * exported from linker scripts. */
             extern uint32_t * __syscalls_flash_start__;
@@ -1121,6 +1120,19 @@
         #endif /* defined( __ARMCC_VERSION ) */
     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
 
+    #if ( configENABLE_MPU == 1 )
+        #if defined( __ARMCC_VERSION )
+            /* Declaration when these variable are defined in code instead of being
+             * exported from linker scripts. */
+            extern uint32_t * __privileged_functions_start__;
+            extern uint32_t * __privileged_functions_end__;
+        #else
+            /* Declaration when these variable are exported from linker scripts. */
+            extern uint32_t __privileged_functions_start__[];
+            extern uint32_t __privileged_functions_end__[];
+        #endif /* defined( __ARMCC_VERSION ) */
+    #endif /* configENABLE_MPU == 1 */
+
     uint32_t ulPC;
 
     #if ( configENABLE_TRUSTZONE == 1 )
@@ -1170,39 +1182,54 @@
             break;
 
         case portSVC_FREE_SECURE_CONTEXT:
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
+            {
+            #endif /* configENABLE_MPU */
+                /* R0 contains TCB being freed and R1 contains the secure
+                 * context handle to be freed. */
+                ulR0 = pulCallerStackAddress[ 0 ];
+                ulR1 = pulCallerStackAddress[ 1 ];
 
-            /* R0 contains TCB being freed and R1 contains the secure
-             * context handle to be freed. */
-            ulR0 = pulCallerStackAddress[ 0 ];
-            ulR1 = pulCallerStackAddress[ 1 ];
-
-            /* Free the secure context. */
-            SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+                /* Free the secure context. */
+                SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
+            #if ( configENABLE_MPU == 1 )
+            }
+            #endif /* configENABLE_MPU */
             break;
     #endif /* configENABLE_TRUSTZONE */
 
         case portSVC_START_SCHEDULER:
-            #if ( configENABLE_TRUSTZONE == 1 )
+            #if ( configENABLE_MPU == 1 )
+            if( ( ulPC >= ( uint32_t ) __privileged_functions_start__ ) &&
+                ( ulPC <= ( uint32_t ) __privileged_functions_end__ ) )
             {
-                /* De-prioritize the non-secure exceptions so that the
-                 * non-secure pendSV runs at the lowest priority. */
-                SecureInit_DePrioritizeNSExceptions();
+            #endif /* configENABLE_MPU */
+                #if ( configENABLE_TRUSTZONE == 1 )
+                {
+                    /* De-prioritize the non-secure exceptions so that the
+                     * non-secure pendSV runs at the lowest priority. */
+                    SecureInit_DePrioritizeNSExceptions();
 
-                /* Initialize the secure context management system. */
-                SecureContext_Init();
+                    /* Initialize the secure context management system. */
+                    SecureContext_Init();
+                }
+                #endif /* configENABLE_TRUSTZONE */
+
+                #if ( configENABLE_FPU == 1 )
+                {
+                    /* Setup the Floating Point Unit (FPU). */
+                    prvSetupFPU();
+                }
+                #endif /* configENABLE_FPU */
+
+                /* Setup the context of the first task so that the first task starts
+                 * executing. */
+                vRestoreContextOfFirstTask();
+            #if ( configENABLE_MPU == 1 )
             }
-            #endif /* configENABLE_TRUSTZONE */
-
-            #if ( configENABLE_FPU == 1 )
-            {
-                /* Setup the Floating Point Unit (FPU). */
-                prvSetupFPU();
-            }
-            #endif /* configENABLE_FPU */
-
-            /* Setup the context of the first task so that the first task starts
-             * executing. */
-            vRestoreContextOfFirstTask();
+            #endif /* configENABLE_MPU */
             break;
 
     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )