mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-01 11:53:53 -04:00
ARMv8.1-M: Add task dedicated PAC key support (#1195)
armv8.1-m: Add task dedicated PAC key To harden the security, each task is assigned a dedicated PAC key, so that attackers needs to guess the all the tasks' PAC keys right to exploit the system using Return Oriented Programming. The kernel is now updated to support the following: * A PAC key set with a random number generated and is saved in the task's context when a task is created. * As part of scheduling, the task's PAC key is stored/restored to/from the task's context when a task is unscheduled/scheduled from/to run. stack-overflow-check: Introduce portGET_CURRENT_TOP_OF_STACK macro When MPU wrapper v2 is used, the task's context is stored in TCB and `pxTopOfStack`` member of TCB points to the context location in TCB. We, therefore, need to read PSP to find the task's current top of stack. Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
This commit is contained in:
parent
c38427eea4
commit
78e0cc778a
87 changed files with 6662 additions and 3530 deletions
|
@ -169,79 +169,80 @@ typedef void ( * portISR_t )( void );
|
|||
/**
|
||||
* @brief Constants required to manipulate the MPU.
|
||||
*/
|
||||
#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
|
||||
#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
|
||||
|
||||
#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
|
||||
#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
|
||||
#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
|
||||
#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
|
||||
|
||||
#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
|
||||
#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
|
||||
#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
|
||||
#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
|
||||
|
||||
#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
|
||||
#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
|
||||
#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
|
||||
#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
|
||||
|
||||
#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
|
||||
#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
|
||||
#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
|
||||
#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
|
||||
|
||||
#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
|
||||
#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
|
||||
#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
|
||||
#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
|
||||
|
||||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
|
||||
#define portMPU_RBAR_ACCESS_PERMISSIONS_MASK ( 3UL << 1UL )
|
||||
#define portMPU_RBAR_ACCESS_PERMISSIONS_MASK ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR1_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
|
||||
#define portMPU_MAIR_ATTR1_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR2_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
|
||||
#define portMPU_MAIR_ATTR2_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR3_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
|
||||
#define portMPU_MAIR_ATTR3_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR4_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
|
||||
#define portMPU_MAIR_ATTR4_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR5_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
|
||||
#define portMPU_MAIR_ATTR5_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR6_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
|
||||
#define portMPU_MAIR_ATTR6_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR7_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
|
||||
#define portMPU_MAIR_ATTR7_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
|
||||
|
||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||
|
||||
#if ( portARMV8M_MINOR_VERSION >= 1 )
|
||||
/* Enable Privileged eXecute Never MPU attribute for the selected memory
|
||||
* region. */
|
||||
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
|
||||
|
||||
/* Enable Privileged eXecute Never MPU attribute for the selected memory
|
||||
* region. */
|
||||
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
|
||||
#endif /* portARMV8M_MINOR_VERSION >= 1 */
|
||||
|
||||
/* Enable privileged access to unmapped region. */
|
||||
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||
|
||||
/* Enable MPU. */
|
||||
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||
|
||||
/* Expected value of the portMPU_TYPE register. */
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL )
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL )
|
||||
|
||||
/* Extract first address of the MPU region as encoded in the
|
||||
* RBAR (Region Base Address Register) value. */
|
||||
|
@ -380,14 +381,14 @@ typedef void ( * portISR_t )( void );
|
|||
/**
|
||||
* @brief Constants required to check and configure PACBTI security feature implementation.
|
||||
*/
|
||||
#if( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
|
||||
#define portID_ISAR5_REG ( *( ( volatile uint32_t * ) 0xe000ed74 ) )
|
||||
#define portID_ISAR5_REG ( *( ( volatile uint32_t * ) 0xe000ed74 ) )
|
||||
|
||||
#define portCONTROL_UPAC_EN ( 1UL << 7UL )
|
||||
#define portCONTROL_PAC_EN ( 1UL << 6UL )
|
||||
#define portCONTROL_UBTI_EN ( 1UL << 5UL )
|
||||
#define portCONTROL_BTI_EN ( 1UL << 4UL )
|
||||
#define portCONTROL_UPAC_EN ( 1UL << 7UL )
|
||||
#define portCONTROL_PAC_EN ( 1UL << 6UL )
|
||||
#define portCONTROL_UBTI_EN ( 1UL << 5UL )
|
||||
#define portCONTROL_BTI_EN ( 1UL << 4UL )
|
||||
|
||||
#endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -409,7 +410,7 @@ static void prvTaskExitError( void );
|
|||
* @return uint32_t Access permissions.
|
||||
*/
|
||||
static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
|
||||
#endif /* configENABLE_MPU == 1 && configUSE_MPU_WRAPPERS_V1 == 0 */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
|
@ -427,7 +428,7 @@ static void prvTaskExitError( void );
|
|||
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#if( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
|
||||
/**
|
||||
* @brief Configures PACBTI features.
|
||||
|
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
uint32_t ulStackFrameSize, ulSystemCallLocation, i;
|
||||
|
||||
#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__;
|
||||
|
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
* point (i.e. the caller of the MPU_<API>). We need to restore it
|
||||
* when we exit from the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
|
||||
|
||||
/* Store the value of the PSPLIM register before the SVC was raised.
|
||||
* We need to restore it when we exit from the system call. */
|
||||
#if ( portUSE_PSPLIM_REGISTER == 1 )
|
||||
|
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
|
||||
/* Start executing the system call upon returning from this handler. */
|
||||
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
|
||||
|
||||
/* Raise a request to exit from the system call upon finishing the
|
||||
* system call. */
|
||||
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
|
||||
|
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
uint32_t ulStackFrameSize, ulSystemCallLocation, i;
|
||||
|
||||
#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__;
|
||||
|
@ -1541,7 +1546,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
|
||||
ulIndex++;
|
||||
|
||||
#if( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
{
|
||||
/* Check PACBTI security feature configuration before pushing the
|
||||
* CONTROL register's value on task's TCB. */
|
||||
|
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
}
|
||||
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
|
||||
|
||||
#if ( configENABLE_PAC == 1 )
|
||||
{
|
||||
uint32_t ulTaskPacKey[ 4 ], i;
|
||||
|
||||
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
|
||||
ulIndex++;
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_PAC */
|
||||
|
||||
return &( xMPUSettings->ulContext[ ulIndex ] );
|
||||
}
|
||||
|
||||
|
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
|
|||
}
|
||||
#endif /* portPRELOAD_REGISTERS */
|
||||
|
||||
#if ( configENABLE_PAC == 1 )
|
||||
{
|
||||
uint32_t ulTaskPacKey[ 4 ], i;
|
||||
|
||||
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ulTaskPacKey[ i ];
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_PAC */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
|
||||
|
@ -1786,11 +1819,11 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
|||
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
|
||||
portNVIC_SHPR2_REG = 0;
|
||||
|
||||
#if( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
{
|
||||
/* Set the CONTROL register value based on PACBTI security feature
|
||||
* configuration before starting the first task. */
|
||||
( void) prvConfigurePACBTI( pdTRUE );
|
||||
( void ) prvConfigurePACBTI( pdTRUE );
|
||||
}
|
||||
#endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
|
||||
|
||||
|
@ -1990,9 +2023,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
|
|||
if( xSchedulerRunning == pdFALSE )
|
||||
{
|
||||
/* Grant access to all the kernel objects before the scheduler
|
||||
* is started. It is necessary because there is no task running
|
||||
* yet and therefore, we cannot use the permissions of any
|
||||
* task. */
|
||||
* is started. It is necessary because there is no task running
|
||||
* yet and therefore, we cannot use the permissions of any
|
||||
* task. */
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
|
||||
|
@ -2213,7 +2246,7 @@ BaseType_t xPortIsInsideInterrupt( void )
|
|||
#endif /* #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
#if ( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
|
||||
|
||||
static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
|
||||
{
|
||||
|
@ -2225,13 +2258,13 @@ BaseType_t xPortIsInsideInterrupt( void )
|
|||
/* Enable UsageFault exception. */
|
||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
|
||||
|
||||
#if( configENABLE_PAC == 1 )
|
||||
#if ( configENABLE_PAC == 1 )
|
||||
{
|
||||
ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( configENABLE_BTI == 1 )
|
||||
#if ( configENABLE_BTI == 1 )
|
||||
{
|
||||
ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue