Skip to content

Commit 09cc777

Browse files
wearyzenhenrikbrixandersen
authored andcommitted
arch: arm: add per thread unique PAC key support
Add a config option to set unique PAC keys per thread and make sure to retain them during context switch. Signed-off-by: Sudan Landge <[email protected]>
1 parent 8e5f828 commit 09cc777

File tree

8 files changed

+76
-1
lines changed

8 files changed

+76
-1
lines changed

arch/arm/core/cortex_m/swap_helper.S

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright (c) 2013-2014 Wind River Systems, Inc.
33
* Copyright (c) 2017-2019 Nordic Semiconductor ASA.
44
* Copyright (c) 2020 Stephanos Ioannidis <[email protected]>
5+
* Copyright 2025 Arm Limited and/or its affiliates <open-source-[email protected]>
56
*
67
* SPDX-License-Identifier: Apache-2.0
78
*/
@@ -313,6 +314,18 @@ SECTION_FUNC(TEXT, z_arm_pendsv)
313314

314315
#endif
315316

317+
#ifdef CONFIG_ARM_PAC_PER_THREAD
318+
/* Read thread's dedicated PAC key and write them in the privileged PAC key registers.
319+
*/
320+
add r0, r2, #_thread_offset_to_pac_keys
321+
ldmia r0!, {r3-r6}
322+
msr PAC_KEY_P_0, r3
323+
msr PAC_KEY_P_1, r4
324+
msr PAC_KEY_P_2, r5
325+
msr PAC_KEY_P_3, r6
326+
clrm {r3-r6}
327+
#endif /* CONFIG_ARM_PAC_PER_THREAD */
328+
316329
/* load callee-saved + psp from thread */
317330
add r0, r2, #_thread_offset_to_callee_saved
318331
ldmia r0, {r4-r11, ip}

arch/arm/core/cortex_m/thread.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Copyright (c) 2013-2014 Wind River Systems, Inc.
33
* Copyright (c) 2021 Lexmark International, Inc.
4-
* Copyright (c) 2023 Arm Limited
4+
* Copyright (c) 2023, 2025 Arm Limited and/or its affiliates <[email protected]>
55
*
66
* SPDX-License-Identifier: Apache-2.0
77
*/
@@ -20,6 +20,7 @@
2020
#include <zephyr/sys/barrier.h>
2121
#include <stdbool.h>
2222
#include <cmsis_core.h>
23+
#include <zephyr/random/random.h>
2324

2425
#if (MPU_GUARD_ALIGN_AND_SIZE_FLOAT > MPU_GUARD_ALIGN_AND_SIZE)
2526
#define FP_GUARD_EXTRA_SIZE (MPU_GUARD_ALIGN_AND_SIZE_FLOAT - MPU_GUARD_ALIGN_AND_SIZE)
@@ -121,6 +122,12 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, char *sta
121122
#if defined(CONFIG_USERSPACE)
122123
thread->arch.priv_stack_start = 0;
123124
#endif
125+
#endif
126+
#ifdef CONFIG_ARM_PAC_PER_THREAD
127+
/* Generate PAC key and save it in thread context to be set later
128+
* when the thread is actually switched in
129+
*/
130+
sys_csrand_get(&thread->arch.pac_keys, sizeof(struct pac_keys));
124131
#endif
125132
/*
126133
* initial values in all other registers/thread entries are
@@ -541,6 +548,9 @@ void arch_switch_to_main_thread(struct k_thread *main_thread, char *stack_ptr,
541548
#endif
542549
#endif /* CONFIG_BUILTIN_STACK_GUARD */
543550

551+
#ifdef CONFIG_ARM_PAC_PER_THREAD
552+
__set_PAC_KEY_P((uint32_t *)&main_thread->arch.pac_keys);
553+
#endif
544554
/*
545555
* Set PSP to the highest address of the main stack
546556
* before enabling interrupts and jumping to main.

arch/arm/core/offsets/offsets_aarch32.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2013-2014 Wind River Systems, Inc.
3+
* Copyright 2025 Arm Limited and/or its affiliates <[email protected]>
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -32,6 +33,10 @@
3233
GEN_OFFSET_SYM(_thread_arch_t, basepri);
3334
GEN_OFFSET_SYM(_thread_arch_t, swap_return_value);
3435

36+
#if defined(CONFIG_ARM_PAC_PER_THREAD)
37+
GEN_OFFSET_SYM(_thread_arch_t, pac_keys);
38+
#endif
39+
3540
#if defined(CONFIG_CPU_AARCH32_CORTEX_A) || defined(CONFIG_CPU_AARCH32_CORTEX_R)
3641
GEN_OFFSET_SYM(_thread_arch_t, exception_depth);
3742
GEN_OFFSET_SYM(_cpu_arch_t, exc_depth);

arch/arm/include/offsets_short_arch.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2019 Carlo Caione <[email protected]>
3+
* Copyright 2025 Arm Limited and/or its affiliates <[email protected]>
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -59,6 +60,10 @@
5960
(___thread_stack_info_t_start_OFFSET + ___thread_t_stack_info_OFFSET)
6061
#endif
6162

63+
#if defined(CONFIG_ARM_PAC_PER_THREAD)
64+
#define _thread_offset_to_pac_keys \
65+
(___thread_t_arch_OFFSET + ___thread_arch_t_pac_keys_OFFSET)
66+
#endif
6267

6368
/* end - threads */
6469

arch/common/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,23 @@ config ARM_MPU
7676
of full partitioning the default behavior for the ARMv8-M and ARMv8-R MPU
7777
driver.
7878

79+
config ARM_PAC_PER_THREAD
80+
bool "Set cryptographically secure PAC key per thread"
81+
depends on ARM_PAC
82+
depends on ENTROPY_DEVICE_RANDOM_GENERATOR || TIMER_RANDOM_GENERATOR
83+
depends on !USERSPACE
84+
help
85+
Select this option to generate and use unique keys per thread to generate Pointer
86+
Authentication Code.
87+
Internally, sys_csrand_get() is used as part of arch_new_thread() to generate
88+
cryptographically secure random keys, which are saved in the thread's
89+
architecture-specific context. These keys are then loaded into the PAC key registers
90+
before switching to the thread during context switches.
91+
Applications can chose to have hardware based random keys generator by selecting the right
92+
generator from RNG_GENERATOR_CHOICE or by selecting TIMER_RANDOM_GENERATOR for testing
93+
with pseudo random keys.
94+
Note: GCC version 14.3 or higher is needed to support this option.
95+
7996
config ARM_PAC
8097
bool
8198
help

doc/hardware/arch/arm_cortex_m.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,11 @@ automatically selected based on the branch protection option chosen for
459459
:kconfig:option:`CONFIG_ARM_PACBTI`. These configuration options enforce PACBTI by enabling
460460
corresponding PACBTI bits in CONTROL register and in the FVP.
461461

462+
To further enhance pointer authentication, Zephyr supports using cryptographically secure,
463+
per-thread PAC keys by enabling :kconfig:option:`CONFIG_ARM_PAC_PER_THREAD`.
464+
For more details on key generation sources and configuration, refer to the Kconfig help for
465+
:kconfig:option:`CONFIG_ARM_PAC_PER_THREAD`.
466+
462467
**Limitations:**
463468

464469
- Only builds targeting Armv8.1-M Mainline processors with PACBTI hardware support (e.g.,

include/zephyr/arch/arm/thread.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2017 Intel Corporation
3+
* Copyright 2025 Arm Limited and/or its affiliates <[email protected]>
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -60,6 +61,15 @@ struct _preempt_float {
6061
};
6162
#endif
6263

64+
#if defined(CONFIG_ARM_PAC_PER_THREAD)
65+
struct pac_keys {
66+
uint32_t key_0;
67+
uint32_t key_1;
68+
uint32_t key_2;
69+
uint32_t key_3;
70+
};
71+
#endif
72+
6373
struct _thread_arch {
6474

6575
/* interrupt locking key */
@@ -134,6 +144,10 @@ struct _thread_arch {
134144
#endif
135145
#endif
136146
#endif
147+
148+
#if defined(CONFIG_ARM_PAC_PER_THREAD)
149+
struct pac_keys pac_keys;
150+
#endif
137151
};
138152

139153
#if defined(CONFIG_FPU_SHARING) && defined(CONFIG_MPU_STACK_GUARD)

modules/cmsis_6/cmsis_core_m_defaults.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,10 @@ typedef enum {
147147
#error "Unknown Cortex-M device"
148148
#endif
149149

150+
#ifdef CONFIG_ARM_PAC
151+
/* This provides apis to set/get PAC keys */
152+
#define __ARM_FEATURE_PAUTH 1
153+
#include <m-profile/armv81m_pac.h>
154+
#endif
155+
150156
#endif /* ZEPHYR_MODULES_CMSIS_6_CMSIS_CORE_M_DEFAULTS_H_ */

0 commit comments

Comments
 (0)