Skip to content

Commit 05a1578

Browse files
committed
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 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>
1 parent 924fc4f commit 05a1578

File tree

63 files changed

+4232
-812
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4232
-812
lines changed

.github/.cSpellWords.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ CLKSOURCE
106106
CLKSTA
107107
CLRB
108108
CLRF
109+
clrm
109110
CLRPSW
110111
CMCNT
111112
CMCON
@@ -678,6 +679,7 @@ pylint
678679
pytest
679680
pyyaml
680681
RAMPZ
682+
randomisation
681683
RASR
682684
Rationalised
683685
Raynald

portable/ARMv8M/non_secure/port.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
#include "mpu_wrappers.h"
4242
#include "mpu_syscall_numbers.h"
4343

44+
#if ( configENABLE_PAC == 1 )
45+
#include <stdlib.h>
46+
#include <time.h>
47+
#endif /* configENABLE_PAC */
48+
4449
/* Portasm includes. */
4550
#include "portasm.h"
4651

@@ -1582,6 +1587,18 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
15821587
}
15831588
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
15841589

1590+
#if ( configENABLE_PAC == 1 )
1591+
{
1592+
static uint32_t pulTaskPacKey[4];
1593+
vPortGenerateTaskRandomPacKey( pulTaskPacKey );
1594+
for ( uint8_t i = 0; i < ( portPAC_KEY_SIZE_BYTES / sizeof( uint32_t ) ); i++ )
1595+
{
1596+
xMPUSettings->ulContext[ ulIndex ] = pulTaskPacKey[i];
1597+
ulIndex++;
1598+
}
1599+
}
1600+
#endif /* configENABLE_PAC */
1601+
15851602
return &( xMPUSettings->ulContext[ ulIndex ] );
15861603
}
15871604

@@ -1664,6 +1681,18 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
16641681
}
16651682
#endif /* portPRELOAD_REGISTERS */
16661683

1684+
#if ( configENABLE_PAC == 1 )
1685+
{
1686+
static uint32_t pulTaskPacKey[4];
1687+
vPortGenerateTaskRandomPacKey( pulTaskPacKey );
1688+
for ( uint8_t i = 0; i < ( portPAC_KEY_SIZE_BYTES / sizeof( uint32_t ) ); i++ )
1689+
{
1690+
pxTopOfStack--;
1691+
*pxTopOfStack = pulTaskPacKey[i];
1692+
}
1693+
}
1694+
#endif /* configENABLE_PAC */
1695+
16671696
return pxTopOfStack;
16681697
}
16691698

@@ -2245,5 +2274,22 @@ BaseType_t xPortIsInsideInterrupt( void )
22452274
return ulControl;
22462275
}
22472276

2277+
#if ( configENABLE_PAC == 1 )
2278+
__attribute__( ( weak ) ) void vPortGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey )
2279+
{
2280+
static BaseType_t isSeeded = pdFALSE;
2281+
if ( isSeeded == pdFALSE )
2282+
{
2283+
srand(time(NULL));
2284+
isSeeded = pdTRUE;
2285+
}
2286+
2287+
for ( uint8_t i = 0; i < ( portPAC_KEY_SIZE_BYTES / sizeof( uint32_t ) ); i++ )
2288+
{
2289+
pulTaskPacKey[i] = rand();
2290+
}
2291+
}
2292+
#endif /* configENABLE_PAC */
2293+
22482294
#endif /* configENABLE_PAC == 1 || configENABLE_BTI == 1 */
22492295
/*-----------------------------------------------------------*/

portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portasm.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@
9999
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
100100
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
101101
" \n"
102+
#if ( configENABLE_PAC == 1 )
103+
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
104+
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
105+
" msr PAC_KEY_P_1, r4 \n"
106+
" msr PAC_KEY_P_2, r5 \n"
107+
" msr PAC_KEY_P_3, r6 \n"
108+
" clrm {r3-r6} \n"
109+
#endif /* configENABLE_PAC */
110+
" \n"
102111
" restore_special_regs_first_task: \n"
103112
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
104113
" msr psp, r3 \n"
@@ -131,6 +140,14 @@
131140
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
132141
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
133142
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
143+
#if ( configENABLE_PAC == 1 )
144+
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
145+
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
146+
" msr PAC_KEY_P_2, r2 \n"
147+
" msr PAC_KEY_P_1, r3 \n"
148+
" msr PAC_KEY_P_0, r4 \n"
149+
" clrm {r1-r4} \n"
150+
#endif /* configENABLE_PAC */
134151
" \n"
135152
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
136153
" ldr r4, =xSecureContext \n"
@@ -300,6 +317,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
300317
" mrs r4, psplim \n" /* r4 = PSPLIM. */
301318
" mrs r5, control \n" /* r5 = CONTROL. */
302319
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
320+
#if ( configENABLE_PAC == 1 )
321+
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
322+
" mrs r4, PAC_KEY_P_1 \n"
323+
" mrs r5, PAC_KEY_P_2 \n"
324+
" mrs r6, PAC_KEY_P_3 \n"
325+
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
326+
" clrm {r3-r6} \n"
327+
#endif /* configENABLE_PAC */
303328
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
304329
" \n"
305330
" select_next_task: \n"
@@ -357,6 +382,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
357382
" ldr r1, [r3] \n" /* r1 = pxCurrentTCB.*/
358383
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
359384
" \n"
385+
#if ( configENABLE_PAC == 1 )
386+
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
387+
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
388+
" msr PAC_KEY_P_1, r4 \n"
389+
" msr PAC_KEY_P_2, r5 \n"
390+
" msr PAC_KEY_P_3, r6 \n"
391+
" clrm {r3-r6} \n"
392+
#endif /* configENABLE_PAC */
393+
" \n"
360394
" restore_special_regs: \n"
361395
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
362396
" msr psp, r3 \n"
@@ -434,6 +468,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
434468
" mrs r1, psplim \n" /* r1 = PSPLIM. */
435469
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
436470
" stmdb r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
471+
" \n"
472+
#if ( configENABLE_PAC == 1 )
473+
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
474+
" mrs r4, PAC_KEY_P_2 \n"
475+
" mrs r5, PAC_KEY_P_1 \n"
476+
" mrs r6, PAC_KEY_P_0 \n"
477+
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
478+
" clrm {r3-r6} \n"
479+
#endif /* configENABLE_PAC */
437480
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
438481
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
439482
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
@@ -451,6 +494,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
451494
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */
452495
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
453496
" \n"
497+
#if ( configENABLE_PAC == 1 )
498+
" ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
499+
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
500+
" msr PAC_KEY_P_2, r4 \n"
501+
" msr PAC_KEY_P_1, r5 \n"
502+
" msr PAC_KEY_P_0, r6 \n"
503+
" clrm {r3-r6} \n"
504+
#endif /* configENABLE_PAC */
505+
" \n"
454506
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
455507
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */
456508
" mov lr, r4 \n" /* LR = r4. */

portable/ARMv8M/non_secure/portable/GCC/ARM_CM33_NTZ/portasm.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@
9999
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
100100
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
101101
" \n"
102+
#if ( configENABLE_PAC == 1 )
103+
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
104+
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
105+
" msr PAC_KEY_P_1, r3 \n"
106+
" msr PAC_KEY_P_2, r4 \n"
107+
" msr PAC_KEY_P_3, r5 \n"
108+
" clrm {r2-r5} \n"
109+
#endif /* configENABLE_PAC */
110+
" \n"
102111
" restore_special_regs_first_task: \n"
103112
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
104113
" msr psp, r2 \n"
@@ -129,6 +138,15 @@
129138
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
130139
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
131140
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
141+
#if ( configENABLE_PAC == 1 )
142+
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
143+
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
144+
" msr PAC_KEY_P_2, r2 \n"
145+
" msr PAC_KEY_P_1, r3 \n"
146+
" msr PAC_KEY_P_0, r4 \n"
147+
" clrm {r1-r4} \n"
148+
#endif /* configENABLE_PAC */
149+
" \n"
132150
" \n"
133151
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
134152
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
@@ -279,6 +297,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
279297
" mrs r3, psplim \n" /* r3 = PSPLIM. */
280298
" mrs r4, control \n" /* r4 = CONTROL. */
281299
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
300+
#if ( configENABLE_PAC == 1 )
301+
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
302+
" mrs r3, PAC_KEY_P_1 \n"
303+
" mrs r4, PAC_KEY_P_2 \n"
304+
" mrs r5, PAC_KEY_P_3 \n"
305+
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
306+
" clrm {r2-r5} \n"
307+
#endif /* configENABLE_PAC */
282308
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
283309
" \n"
284310
" select_next_task: \n"
@@ -336,6 +362,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
336362
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
337363
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
338364
" \n"
365+
#if ( configENABLE_PAC == 1 )
366+
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
367+
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
368+
" msr PAC_KEY_P_1, r3 \n"
369+
" msr PAC_KEY_P_2, r4 \n"
370+
" msr PAC_KEY_P_3, r5 \n"
371+
" clrm {r2-r5} \n"
372+
#endif /* configENABLE_PAC */
373+
" \n"
339374
" restore_special_regs: \n"
340375
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
341376
" msr psp, r2 \n"
@@ -381,6 +416,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
381416
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
382417
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
383418
" \n"
419+
#if ( configENABLE_PAC == 1 )
420+
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
421+
" mrs r2, PAC_KEY_P_2 \n"
422+
" mrs r3, PAC_KEY_P_1 \n"
423+
" mrs r4, PAC_KEY_P_0 \n"
424+
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
425+
" clrm {r1-r4} \n"
426+
#endif /* configENABLE_PAC */
427+
" \n"
384428
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
385429
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
386430
" str r0, [r1] \n" /* Save the new top of stack in TCB. */
@@ -397,6 +441,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
397441
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
398442
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
399443
" \n"
444+
#if ( configENABLE_PAC == 1 )
445+
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
446+
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
447+
" msr PAC_KEY_P_2, r3 \n"
448+
" msr PAC_KEY_P_1, r4 \n"
449+
" msr PAC_KEY_P_0, r5 \n"
450+
" clrm {r2-r5} \n"
451+
#endif /* configENABLE_PAC */
452+
" \n"
400453
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
401454
" \n"
402455
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

0 commit comments

Comments
 (0)