1 /* $NetBSD: exec_machdep.c,v 1.10 2021/09/23 15:19:03 ryo Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 34 __KERNEL_RCSID(1, "$NetBSD: exec_machdep.c,v 1.10 2021/09/23 15:19:03 ryo Exp $"); 35 36 #include "opt_compat_netbsd.h" 37 #include "opt_compat_netbsd32.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/proc.h> 42 #include <sys/exec.h> 43 #include <sys/cprng.h> 44 45 #include <uvm/uvm_extern.h> 46 47 #include <compat/common/compat_util.h> 48 #include <sys/exec_elf.h> /* mandatory */ 49 50 #ifdef COMPAT_NETBSD32 51 #include <compat/netbsd32/netbsd32_exec.h> 52 #endif 53 54 #include <aarch64/armreg.h> 55 #include <aarch64/frame.h> 56 #include <aarch64/machdep.h> 57 58 #include <arm/cpufunc.h> 59 60 #if EXEC_ELF64 61 int 62 aarch64_netbsd_elf64_probe(struct lwp *l, struct exec_package *epp, void *eh0, 63 char *itp, vaddr_t *start_p) 64 { 65 return 0; 66 } 67 #endif 68 69 #if EXEC_ELF32 70 int 71 aarch64_netbsd_elf32_probe(struct lwp *l, struct exec_package *epp, void *eh0, 72 char *itp, vaddr_t *start_p) 73 { 74 const Elf32_Ehdr * const eh = eh0; 75 const bool elf_aapcs_p = 76 (eh->e_flags & EF_ARM_EABIMASK) >= EF_ARM_EABI_VER4; 77 78 /* OABI not support */ 79 if (!elf_aapcs_p) 80 return ENOEXEC; 81 #ifdef __AARCH64EB__ 82 /* BE32 not support */ 83 if ((eh->e_flags & EF_ARM_BE8) == 0) 84 return ENOEXEC; 85 #endif 86 87 /* 88 * require aarch32 feature. 89 * XXX should consider some cluster may have no aarch32? 90 */ 91 if (__SHIFTOUT(l->l_cpu->ci_id.ac_aa64pfr0, ID_AA64PFR0_EL1_EL0) != 92 ID_AA64PFR0_EL1_EL0_64_32) 93 return ENOEXEC; 94 95 /* 96 * Copy (if any) the machine_arch of the executable to the proc. 97 */ 98 CTASSERT(sizeof(l->l_proc->p_md.md_march32) == 99 sizeof(epp->ep_machine_arch)); 100 if (epp->ep_machine_arch[0] != 0) 101 strlcpy(l->l_proc->p_md.md_march32, epp->ep_machine_arch, 102 sizeof(l->l_proc->p_md.md_march32)); 103 104 return 0; 105 } 106 #endif 107 108 void 109 aarch64_setregs_ptrauth(struct lwp *l, bool randomize) 110 { 111 #ifdef ARMV83_PAC 112 if (!aarch64_pac_enabled) 113 return; 114 115 if (randomize) { 116 cprng_strong(kern_cprng, l->l_md.md_ia_user, 117 sizeof(l->l_md.md_ia_user), 0); 118 cprng_strong(kern_cprng, l->l_md.md_ib_user, 119 sizeof(l->l_md.md_ib_user), 0); 120 cprng_strong(kern_cprng, l->l_md.md_da_user, 121 sizeof(l->l_md.md_da_user), 0); 122 cprng_strong(kern_cprng, l->l_md.md_db_user, 123 sizeof(l->l_md.md_db_user), 0); 124 cprng_strong(kern_cprng, l->l_md.md_ga_user, 125 sizeof(l->l_md.md_ga_user), 0); 126 } else { 127 memset(l->l_md.md_ia_user, 0, 128 sizeof(l->l_md.md_ia_user)); 129 memset(l->l_md.md_ib_user, 0, 130 sizeof(l->l_md.md_ib_user)); 131 memset(l->l_md.md_da_user, 0, 132 sizeof(l->l_md.md_da_user)); 133 memset(l->l_md.md_db_user, 0, 134 sizeof(l->l_md.md_db_user)); 135 memset(l->l_md.md_ga_user, 0, 136 sizeof(l->l_md.md_ga_user)); 137 } 138 #endif 139 } 140 141 void 142 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 143 { 144 struct proc * const p = l->l_proc; 145 struct trapframe * const tf = lwp_trapframe(l); 146 147 aarch64_setregs_ptrauth(l, true); 148 149 p->p_flag &= ~PK_32; 150 151 /* 152 * void __start(void (*cleanup)(void), const Obj_Entry *obj, 153 * struct ps_strings *ps_strings); 154 */ 155 memset(tf, 0, sizeof(*tf)); 156 tf->tf_reg[2] = p->p_psstrp; 157 tf->tf_pc = pack->ep_entry; 158 tf->tf_sp = stack & -16L; 159 tf->tf_spsr = SPSR_M_EL0T; 160 } 161