Associate secure context with task handle

The secure side context management code now checks that the secure
context being saved or restored belongs to the task being switched-out
or switched-in respectively.

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
This commit is contained in:
Gaurav Aggarwal 2021-08-18 17:31:22 -07:00
parent 66466793d5
commit f87404b56f
53 changed files with 1796 additions and 1353 deletions

View file

@ -35,6 +35,9 @@
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
{
/* pxSecureContext value is in r0. */

View file

@ -31,6 +31,9 @@
/* Secure port macros. */
#include "secure_port_macros.h"
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
{
/* pxSecureContext value is in r0. */

View file

@ -28,6 +28,13 @@
SECTION .text:CODE:NOROOT(2)
THUMB
/* Including FreeRTOSConfig.h here will cause build errors if the header file
contains code not understood by the assembler - for example the 'extern' keyword.
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
the code is included in C files but excluded by the preprocessor in assembly
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
#include "FreeRTOSConfig.h"
PUBLIC SecureContext_LoadContextAsm
PUBLIC SecureContext_SaveContextAsm

View file

@ -28,6 +28,13 @@
SECTION .text:CODE:NOROOT(2)
THUMB
/* Including FreeRTOSConfig.h here will cause build errors if the header file
contains code not understood by the assembler - for example the 'extern' keyword.
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
the code is included in C files but excluded by the preprocessor in assembly
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
#include "FreeRTOSConfig.h"
PUBLIC SecureContext_LoadContextAsm
PUBLIC SecureContext_SaveContextAsm
/*-----------------------------------------------------------*/

View file

@ -50,11 +50,6 @@
*/
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
/**
* @brief Invalid context ID.
*/
#define securecontextINVALID_CONTEXT_ID 0UL
/**
* @brief Maximum number of secure contexts.
*/
@ -70,11 +65,15 @@ SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
/*-----------------------------------------------------------*/
/**
* @brief Get a free context from the secure context pool (xSecureContexts).
* @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
*
* @return Index of a free context in the xSecureContexts array.
* This function ensures that only one secure context is allocated for a task.
*
* @param[in] pvTaskHandle The task handle for which the secure context is allocated.
*
* @return Index of a free secure context in the xSecureContexts array.
*/
static uint32_t ulGetSecureContext( void );
static uint32_t ulGetSecureContext( void * pvTaskHandle );
/**
* @brief Return the secure context to the secure context pool (xSecureContexts).
@ -88,16 +87,26 @@ extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
/*-----------------------------------------------------------*/
static uint32_t ulGetSecureContext( void )
static uint32_t ulGetSecureContext( void * pvTaskHandle )
{
uint32_t ulSecureContextIndex;
/* Start with invalid index. */
uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
for( ulSecureContextIndex = 0; ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS; ulSecureContextIndex++ )
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
{
if( ( xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer == NULL ) &&
( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == NULL ) &&
( xSecureContexts[ ulSecureContextIndex ].pucStackStart == NULL ) )
if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
( xSecureContexts[ i ].pucStackLimit == NULL ) &&
( xSecureContexts[ i ].pucStackStart == NULL ) &&
( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
{
ulSecureContextIndex = i;
}
else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
{
/* A task can only have one secure context. Do not allocate a second
* context for the same task. */
ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
break;
}
}
@ -111,20 +120,25 @@ static void vReturnSecureContext( uint32_t ulSecureContextIndex )
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
{
uint32_t ulIPSR, i;
static uint32_t ulSecureContextsInitialized = 0;
/* Read the Interrupt Program Status Register (IPSR) value. */
secureportREAD_IPSR( ulIPSR );
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
* when the processor is running in the Thread Mode. */
if( ulIPSR != 0 )
if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
{
/* Ensure to initialize secure contexts only once. */
ulSecureContextsInitialized = 1;
/* No stack for thread mode until a task's context is loaded. */
secureportSET_PSPLIM( securecontextNO_STACK );
secureportSET_PSP( securecontextNO_STACK );
@ -135,6 +149,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
xSecureContexts[ i ].pucCurrentStackPointer = NULL;
xSecureContexts[ i ].pucStackLimit = NULL;
xSecureContexts[ i ].pucStackStart = NULL;
xSecureContexts[ i ].pvTaskHandle = NULL;
}
#if ( configENABLE_MPU == 1 )
@ -154,28 +169,35 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
#if ( configENABLE_MPU == 1 )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged )
uint32_t ulIsTaskPrivileged,
void * pvTaskHandle )
#else /* configENABLE_MPU */
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
void * pvTaskHandle )
#endif /* configENABLE_MPU */
{
uint8_t * pucStackMemory = NULL;
uint8_t * pucStackLimit;
uint32_t ulIPSR, ulSecureContextIndex;
SecureContextHandle_t xSecureContextHandle;
SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
#if ( configENABLE_MPU == 1 )
uint32_t * pulCurrentStackPointer = NULL;
#endif /* configENABLE_MPU */
/* 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. */
if( ulIPSR != 0 )
* when the processor is running in the Thread Mode.
* Also do nothing, if a secure context us already loaded. PSPLIM is set to
* securecontextNO_STACK when no secure context is loaded. */
if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
{
/* Ontain a free secure context. */
ulSecureContextIndex = ulGetSecureContext();
ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
/* Were we able to get a free context? */
if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
@ -197,6 +219,8 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
* programmed in the PSPLIM register on context switch.*/
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
#if ( configENABLE_MPU == 1 )
{
/* Store the correct CONTROL value for the task on the stack.
@ -229,10 +253,6 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
/* Ensure to never return 0 as a valid context handle. */
xSecureContextHandle = ulSecureContextIndex + 1UL;
}
else
{
xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
}
}
}
@ -240,7 +260,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
{
uint32_t ulIPSR, ulSecureContextIndex;
@ -256,38 +276,61 @@ secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandl
{
ulSecureContextIndex = xSecureContextHandle - 1UL;
/* Free the stack space. */
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
/* Ensure that the secure context being deleted is associated with
* the task. */
if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
{
/* Free the stack space. */
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
/* Return the context back to the free contexts pool. */
vReturnSecureContext( ulSecureContextIndex );
/* Return the secure context back to the free secure contexts pool. */
vReturnSecureContext( ulSecureContextIndex );
}
}
}
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
{
uint8_t * pucStackLimit;
uint32_t ulSecureContextIndex;
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
{
ulSecureContextIndex = xSecureContextHandle - 1UL;
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
secureportREAD_PSPLIM( pucStackLimit );
/* Ensure that no secure context is loaded and the task is loading it's
* own context. */
if( ( pucStackLimit == securecontextNO_STACK ) &&
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
{
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
}
}
}
/*-----------------------------------------------------------*/
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
{
uint8_t * pucStackLimit;
uint32_t ulSecureContextIndex;
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
{
ulSecureContextIndex = xSecureContextHandle - 1UL;
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
secureportREAD_PSPLIM( pucStackLimit );
/* Ensure that task's context is loaded and the task is saving it's own
* context. */
if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
{
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
}
}
}
/*-----------------------------------------------------------*/

View file

@ -37,7 +37,12 @@
/**
* @brief PSP value when no secure context is loaded.
*/
#define securecontextNO_STACK 0x0
#define securecontextNO_STACK 0x0
/**
* @brief Invalid context ID.
*/
#define securecontextINVALID_CONTEXT_ID 0UL
/*-----------------------------------------------------------*/
/**
@ -51,6 +56,7 @@ typedef struct SecureContext
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
uint8_t * pucStackStart; /**< First location of the stack memory. */
void * pvTaskHandle; /**< Task handle of the task this context is associated with. */
} SecureContext_t;
/*-----------------------------------------------------------*/
@ -85,9 +91,11 @@ void SecureContext_Init( void );
*/
#if ( configENABLE_MPU == 1 )
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged );
uint32_t ulIsTaskPrivileged,
void * pvTaskHandle );
#else /* configENABLE_MPU */
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
void * pvTaskHandle );
#endif /* configENABLE_MPU */
/**
@ -99,7 +107,7 @@ void SecureContext_Init( void );
* @param[in] xSecureContextHandle Context handle corresponding to the
* context to be freed.
*/
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle );
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
/**
* @brief Loads the given context.
@ -110,7 +118,7 @@ void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle );
* @param[in] xSecureContextHandle Context handle corresponding to the context
* to be loaded.
*/
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle );
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
/**
* @brief Saves the given context.
@ -121,6 +129,6 @@ void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle );
* @param[in] xSecureContextHandle Context handle corresponding to the context
* to be saved.
*/
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle );
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
#endif /* __SECURE_CONTEXT_H__ */

View file

@ -448,9 +448,3 @@ size_t xPortGetMinimumEverFreeHeapSize( void )
return xMinimumEverFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
void vPortInitialiseBlocks( void )
{
/* This just exists to keep the linker quiet. */
}
/*-----------------------------------------------------------*/

View file

@ -48,4 +48,18 @@ void * pvPortMalloc( size_t xWantedSize );
*/
void vPortFree( void * pv );
/**
* @brief Get the free heap size.
*
* @return Free heap size.
*/
size_t xPortGetFreeHeapSize( void );
/**
* @brief Get the minimum ever free heap size.
*
* @return Minimum ever free heap size.
*/
size_t xPortGetMinimumEverFreeHeapSize( void );
#endif /* __SECURE_HEAP_H__ */

View file

@ -67,6 +67,12 @@
#define secureportSET_PSP( pucCurrentStackPointer ) \
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
/**
* @brief Read the PSPLIM value in the given variable.
*/
#define secureportREAD_PSPLIM( pucOutStackLimit ) \
__asm volatile ( "mrs %0, psplim" : "=r" ( pucOutStackLimit ) )
/**
* @brief Set the PSPLIM to the given value.
*/