Initial reservations are created via the standard do_mmap() in binfmt_elf, and as a result their permissions are calculated via the standard helper that calls arch_user_ptr_owning_perms_from_prot(). The latter relies on the current value of PCC to decide whether to return System and Executive, so we need to ensure that this value is well-defined when binfmt_elf creates the mappings.
morello_thread_init_user() is called from arch_setup_new_exec(), which itself is called very early by binfmt_elf. This is therefore a good place to set PCC to a temporary value with all permissions, while waiting for the final value set by morello_thread_start().
Signed-off-by: Kevin Brodsky kevin.brodsky@arm.com --- arch/arm64/kernel/morello.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/arch/arm64/kernel/morello.c b/arch/arm64/kernel/morello.c index 2dbfa49c23f7..a445d3aca710 100644 --- a/arch/arm64/kernel/morello.c +++ b/arch/arm64/kernel/morello.c @@ -164,6 +164,22 @@ void morello_thread_init_user(void)
write_sysreg(cctlr, cctlr_el0); morello_state->cctlr = cctlr; + + if (is_pure_task()) { + /* + * arch_user_ptr_owning_perms_from_prot() checks the permissions + * of PCC to decide which permissions to return. It ends up + * being called from binfmt_elf before the thread has even + * started, at which point the value of PCC will be that of the + * old process. To avoid this issue, set PCC to a temporary + * value with all permissions, so that initial reservations + * (executable, interpreter, etc.) are assigned appropriate + * permissions (especially Executive). This value is never + * visible to userspace as morello_thread_start() will set the + * final value. + */ + task_pt_regs(current)->pcc = cheri_user_root_cap; + } }
void morello_thread_save_user_state(struct task_struct *tsk)