Skip to content

Commit

Permalink
armv8.1-m: Add task dedicated PAC key
Browse files Browse the repository at this point in the history
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 pushed onto the task's stack when a task is created.

* As part of scheduling, the task's PAC key is stacked/unstacked
to/from the task's stack when a task is unscheduled/scheduled
from/to run.

Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
  • Loading branch information
AhmedIsmail02 committed Nov 19, 2024
1 parent 5934d2d commit d7e9592
Show file tree
Hide file tree
Showing 62 changed files with 4,230 additions and 812 deletions.
46 changes: 46 additions & 0 deletions portable/ARMv8M/non_secure/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
#include "mpu_wrappers.h"
#include "mpu_syscall_numbers.h"

#if ( configENABLE_PAC == 1 )
#include <stdlib.h>
#include <time.h>
#endif /* configENABLE_PAC */

/* Portasm includes. */
#include "portasm.h"

Expand Down Expand Up @@ -1582,6 +1587,18 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
}
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */

#if ( configENABLE_PAC == 1 )
{
static uint32_t pulTaskPacKey[4];
vPortGenerateTaskRandomPacKey( pulTaskPacKey );
for ( uint8_t i = 0; i < ( portPAC_KEY_SIZE_BYTES / sizeof( uint32_t ) ); i++ )
{
xMPUSettings->ulContext[ ulIndex ] = pulTaskPacKey[i];
ulIndex++;
}
}
#endif /* configENABLE_PAC */

return &( xMPUSettings->ulContext[ ulIndex ] );
}

Expand Down Expand Up @@ -1664,6 +1681,18 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
}
#endif /* portPRELOAD_REGISTERS */

#if ( configENABLE_PAC == 1 )
{
static uint32_t pulTaskPacKey[4];
vPortGenerateTaskRandomPacKey( pulTaskPacKey );
for ( uint8_t i = 0; i < ( portPAC_KEY_SIZE_BYTES / sizeof( uint32_t ) ); i++ )
{
pxTopOfStack--;
*pxTopOfStack = pulTaskPacKey[i];
}
}
#endif /* configENABLE_PAC */

return pxTopOfStack;
}

Expand Down Expand Up @@ -2245,5 +2274,22 @@ BaseType_t xPortIsInsideInterrupt( void )
return ulControl;
}

#if ( configENABLE_PAC == 1 )
__attribute__( ( weak ) ) void vPortGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey )
{
static BaseType_t isSeeded = pdFALSE;
if ( isSeeded == pdFALSE )
{
srand(time(NULL));
isSeeded = pdTRUE;
}

for ( uint8_t i = 0; i < ( portPAC_KEY_SIZE_BYTES / sizeof( uint32_t ) ); i++ )
{
pulTaskPacKey[i] = rand();
}
}
#endif /* configENABLE_PAC */

#endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
/*-----------------------------------------------------------*/
52 changes: 52 additions & 0 deletions portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n"
#endif /* configENABLE_PAC */
" \n"
" restore_special_regs_first_task: \n"
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n"
Expand Down Expand Up @@ -131,6 +140,14 @@
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n"
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, =xSecureContext \n"
Expand Down Expand Up @@ -300,6 +317,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r4, psplim \n" /* r4 = PSPLIM. */
" mrs r5, control \n" /* r5 = CONTROL. */
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_1 \n"
" mrs r5, PAC_KEY_P_2 \n"
" mrs r6, PAC_KEY_P_3 \n"
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r3-r6} \n"
#endif /* configENABLE_PAC */
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n"
" select_next_task: \n"
Expand Down Expand Up @@ -357,6 +382,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n"
#endif /* configENABLE_PAC */
" \n"
" restore_special_regs: \n"
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n"
Expand Down Expand Up @@ -434,6 +468,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmdb r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" \n"
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_1 \n"
" mrs r6, PAC_KEY_P_0 \n"
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r3-r6} \n"
#endif /* configENABLE_PAC */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
Expand All @@ -451,6 +494,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n"
#if ( configENABLE_PAC == 1 )
" ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_1, r5 \n"
" msr PAC_KEY_P_0, r6 \n"
" clrm {r3-r6} \n"
#endif /* configENABLE_PAC */
" \n"
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */
" mov lr, r4 \n" /* LR = r4. */
Expand Down
53 changes: 53 additions & 0 deletions portable/ARMv8M/non_secure/portable/GCC/ARM_CM33_NTZ/portasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n"
#endif /* configENABLE_PAC */
" \n"
" restore_special_regs_first_task: \n"
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n"
Expand Down Expand Up @@ -129,6 +138,15 @@
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n"
#endif /* configENABLE_PAC */
" \n"
" \n"
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
Expand Down Expand Up @@ -279,6 +297,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r3, psplim \n" /* r3 = PSPLIM. */
" mrs r4, control \n" /* r4 = CONTROL. */
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_3 \n"
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r2-r5} \n"
#endif /* configENABLE_PAC */
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n"
" select_next_task: \n"
Expand Down Expand Up @@ -336,6 +362,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n"
#endif /* configENABLE_PAC */
" \n"
" restore_special_regs: \n"
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n"
Expand Down Expand Up @@ -381,6 +416,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
" \n"
#if ( configENABLE_PAC == 1 )
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r2, PAC_KEY_P_2 \n"
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_0 \n"
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r1-r4} \n"
#endif /* configENABLE_PAC */
" \n"
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */
Expand All @@ -397,6 +441,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r3 \n"
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_0, r5 \n"
" clrm {r2-r5} \n"
#endif /* configENABLE_PAC */
" \n"
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
" \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
Expand Down
Loading

0 comments on commit d7e9592

Please sign in to comment.