On 06/09/2022 12:16, Sherwin da Cruz wrote:
As per PCuABI specific registers c0-c3 are initialised for purecap applications to make use of. This is set in start_thread(). The macro START_THREAD is specialised to allow returning the value of argc to be placed in x0.
Signed-off-by: Sherwin da Cruz sherwin.dacruz@arm.com
arch/arm64/include/asm/elf.h | 3 +++ arch/arm64/include/asm/processor.h | 35 ++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 9eb86b4cb691..07fb682aa4e6 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -164,6 +164,9 @@ typedef unsigned long elf_greg_t; typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef struct user_fpsimd_state elf_fpregset_t; +#define START_THREAD(elf_ex, regs, elf_entry, bprm) \
- start_thread(regs, elf_entry, bprm->p, bprm->argc, bprm->envc)
- #define SET_PERSONALITY_AARCH64() \ ({ \ current->personality &= ~READ_IMPLIES_EXEC; \
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 5bdecb185f63..b190cfe816f5 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -238,6 +238,35 @@ void tls_preserve_current_state(void); .fpsimd_cpu = NR_CPUS, \ } +static inline int init_gp_regs(struct pt_regs *regs, unsigned long sp,
int argc, int envc)
+{
- int retval = 0;
+#ifdef CONFIG_CHERI_PURECAP_UABI
- unsigned long argv, envp, auxv;
- /*
* TODO [PCuABI]:
* - When argv/envp/auxv is moved off the stack, update the registers x1-x3
* with the new pointer values, and ensure c1-c3 contain appropriate
* capabilities (currently set to csp).
* - Restrict bounds/perms of c1-c3.
*
* In ret_to_user c regs are first loaded then merged with x regs if their values
* are different. Hence we load capabilities in c regs and the value in x regs.
*/
- retval = argc; /* Placed in x0 */
- argv = sp + 1 * sizeof(user_uintptr_t); /* Increment past argc on stack */
- envp = argv + (argc + 1) * sizeof(user_uintptr_t); /* Go past arg vals + NULL */
- auxv = envp + (envc + 1) * sizeof(user_uintptr_t); /* Go past env vals + NULL */
- regs->cregs[1] = regs->cregs[2] = regs->cregs[3] = regs->csp;
- regs->regs[1] = argv;
- regs->regs[2] = envp;
- regs->regs[3] = auxv;
+#endif /* CONFIG_CHERI_PURECAP_UABI */
- return retval;
+}
- static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) { memset(regs, 0, sizeof(*regs));
@@ -248,8 +277,8 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) regs->pmr_save = GIC_PRIO_IRQON; } -static inline void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
+static inline int start_thread(struct pt_regs *regs, unsigned long pc,
{ start_thread_common(regs, pc); regs->pstate = PSR_MODE_EL0t;unsigned long sp, int argc, int envc)
@@ -258,6 +287,8 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc, if (system_supports_morello()) morello_thread_start(regs, pc);
- return init_gp_regs(regs, sp, argc, envc);
As discussed offline, we missed something crucial here: start_thread() is in fact used for both PCuABI and compat64, compat_start_thread() is only used for compat32. This means we end up setting c0-c3 for compat64 too, which turns out to break some binaries. We should probably create a new compat_start_thread() for compat64.
Kevin
} #ifdef CONFIG_COMPAT