1*b5090f27Sriastradh /* $NetBSD: exec_elf.c,v 1.107 2024/12/06 16:19:41 riastradh Exp $ */ 292ce8c6aSad 392ce8c6aSad /*- 4f1ecb271Sad * Copyright (c) 1994, 2000, 2005, 2015, 2020 The NetBSD Foundation, Inc. 592ce8c6aSad * All rights reserved. 692ce8c6aSad * 792ce8c6aSad * This code is derived from software contributed to The NetBSD Foundation 8856f192fSmaxv * by Christos Zoulas and Maxime Villard. 992ce8c6aSad * 1092ce8c6aSad * Redistribution and use in source and binary forms, with or without 1192ce8c6aSad * modification, are permitted provided that the following conditions 1292ce8c6aSad * are met: 1392ce8c6aSad * 1. Redistributions of source code must retain the above copyright 1492ce8c6aSad * notice, this list of conditions and the following disclaimer. 1592ce8c6aSad * 2. Redistributions in binary form must reproduce the above copyright 1692ce8c6aSad * notice, this list of conditions and the following disclaimer in the 1792ce8c6aSad * documentation and/or other materials provided with the distribution. 1892ce8c6aSad * 1992ce8c6aSad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2092ce8c6aSad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2192ce8c6aSad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2292ce8c6aSad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2392ce8c6aSad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2492ce8c6aSad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2592ce8c6aSad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2692ce8c6aSad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2792ce8c6aSad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2892ce8c6aSad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2992ce8c6aSad * POSSIBILITY OF SUCH DAMAGE. 3092ce8c6aSad */ 3192ce8c6aSad 3292ce8c6aSad /* 3392ce8c6aSad * Copyright (c) 1996 Christopher G. Demetriou 3492ce8c6aSad * All rights reserved. 3592ce8c6aSad * 3692ce8c6aSad * Redistribution and use in source and binary forms, with or without 3792ce8c6aSad * modification, are permitted provided that the following conditions 3892ce8c6aSad * are met: 3992ce8c6aSad * 1. Redistributions of source code must retain the above copyright 4092ce8c6aSad * notice, this list of conditions and the following disclaimer. 4192ce8c6aSad * 2. Redistributions in binary form must reproduce the above copyright 4292ce8c6aSad * notice, this list of conditions and the following disclaimer in the 4392ce8c6aSad * documentation and/or other materials provided with the distribution. 4492ce8c6aSad * 3. The name of the author may not be used to endorse or promote products 4592ce8c6aSad * derived from this software without specific prior written permission 4692ce8c6aSad * 4792ce8c6aSad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4892ce8c6aSad * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 4992ce8c6aSad * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 5092ce8c6aSad * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 5192ce8c6aSad * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 5292ce8c6aSad * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5392ce8c6aSad * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5492ce8c6aSad * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5592ce8c6aSad * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5692ce8c6aSad * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5792ce8c6aSad */ 5892ce8c6aSad 5992ce8c6aSad #include <sys/cdefs.h> 60*b5090f27Sriastradh __KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.107 2024/12/06 16:19:41 riastradh Exp $"); 6192ce8c6aSad 6292ce8c6aSad #ifdef _KERNEL_OPT 6392ce8c6aSad #include "opt_pax.h" 6492ce8c6aSad #endif /* _KERNEL_OPT */ 6592ce8c6aSad 6692ce8c6aSad #include <sys/param.h> 67f47e8594Sriastradh #include <sys/types.h> 68f47e8594Sriastradh 69f47e8594Sriastradh #include <sys/bitops.h> 70f47e8594Sriastradh #include <sys/cpu.h> 7192ce8c6aSad #include <sys/exec.h> 7292ce8c6aSad #include <sys/exec_elf.h> 7392ce8c6aSad #include <sys/kauth.h> 74f47e8594Sriastradh #include <sys/kmem.h> 75f47e8594Sriastradh #include <sys/mount.h> 76f47e8594Sriastradh #include <sys/namei.h> 77f47e8594Sriastradh #include <sys/pax.h> 78f47e8594Sriastradh #include <sys/proc.h> 79*b5090f27Sriastradh #include <sys/sdt.h> 80f47e8594Sriastradh #include <sys/signalvar.h> 81f47e8594Sriastradh #include <sys/stat.h> 82f47e8594Sriastradh #include <sys/syscall.h> 83f47e8594Sriastradh #include <sys/vnode.h> 8492ce8c6aSad 8592ce8c6aSad #include <machine/reg.h> 8692ce8c6aSad 8792ce8c6aSad #include <compat/common/compat_util.h> 8892ce8c6aSad 89f8c7c04bSmartin #include <uvm/uvm_param.h> 9092ce8c6aSad 9192ce8c6aSad #define elf_check_header ELFNAME(check_header) 9292ce8c6aSad #define elf_copyargs ELFNAME(copyargs) 93f8cd48a3Schristos #define elf_populate_auxv ELFNAME(populate_auxv) 94d8a274dfSmaxv #define elf_load_interp ELFNAME(load_interp) 9592ce8c6aSad #define elf_load_psection ELFNAME(load_psection) 9692ce8c6aSad #define exec_elf_makecmds ELFNAME2(exec,makecmds) 9792ce8c6aSad #define netbsd_elf_signature ELFNAME2(netbsd,signature) 9811594012Suwe #define netbsd_elf_note ELFNAME2(netbsd,note) 9992ce8c6aSad #define netbsd_elf_probe ELFNAME2(netbsd,probe) 10092ce8c6aSad #define coredump ELFNAMEEND(coredump) 1012210079eSmatt #define elf_free_emul_arg ELFNAME(free_emul_arg) 10292ce8c6aSad 10303cdabd0Smaxv static int 104d8a274dfSmaxv elf_load_interp(struct lwp *, struct exec_package *, char *, 10503cdabd0Smaxv struct exec_vmcmd_set *, u_long *, Elf_Addr *); 106109cfb32Schristos static int 10703cdabd0Smaxv elf_load_psection(struct exec_vmcmd_set *, struct vnode *, const Elf_Phdr *, 1087c099162Smaxv Elf_Addr *, u_long *, int); 10992ce8c6aSad 11092ce8c6aSad int netbsd_elf_signature(struct lwp *, struct exec_package *, Elf_Ehdr *); 11111594012Suwe int netbsd_elf_note(struct exec_package *, const Elf_Nhdr *, const char *, 11211594012Suwe const char *); 11392ce8c6aSad int netbsd_elf_probe(struct lwp *, struct exec_package *, void *, char *, 11492ce8c6aSad vaddr_t *); 11592ce8c6aSad 1162210079eSmatt static void elf_free_emul_arg(void *); 1172210079eSmatt 118406ea0abSchristos #ifdef DEBUG_ELF 119406ea0abSchristos #define DPRINTF(a, ...) printf("%s: " a "\n", __func__, ##__VA_ARGS__) 120406ea0abSchristos #else 121406ea0abSchristos #define DPRINTF(a, ...) 122cbcfdd13Schristos #endif 123406ea0abSchristos 12492ce8c6aSad /* round up and down to page boundaries. */ 12592ce8c6aSad #define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) 12692ce8c6aSad #define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) 12792ce8c6aSad 128109cfb32Schristos static int 1299ed59591Smaxv elf_placedynexec(struct exec_package *epp, Elf_Ehdr *eh, Elf_Phdr *ph) 13092ce8c6aSad { 131713b10dcSdrochner Elf_Addr align, offset; 132713b10dcSdrochner int i; 133713b10dcSdrochner 13400cf4274Schristos for (align = 1, i = 0; i < eh->e_phnum; i++) 135713b10dcSdrochner if (ph[i].p_type == PT_LOAD && ph[i].p_align > align) 136713b10dcSdrochner align = ph[i].p_align; 13792ce8c6aSad 1386b2e8a53Schristos offset = (Elf_Addr)pax_aslr_exec_offset(epp, align); 139006dc29cSchs if (offset < epp->ep_vm_minaddr) 140006dc29cSchs offset = roundup(epp->ep_vm_minaddr, align); 141109cfb32Schristos if ((offset & (align - 1)) != 0) { 142109cfb32Schristos DPRINTF("bad offset=%#jx align=%#jx", 143109cfb32Schristos (uintmax_t)offset, (uintmax_t)align); 144*b5090f27Sriastradh return SET_ERROR(EINVAL); 145109cfb32Schristos } 146f64aeb0dSreinoud 14792ce8c6aSad for (i = 0; i < eh->e_phnum; i++) 148b691db09Schristos ph[i].p_vaddr += offset; 149ab77483fSmatt epp->ep_entryoffset = offset; 1506d16572eSchristos eh->e_entry += offset; 151109cfb32Schristos return 0; 15292ce8c6aSad } 15392ce8c6aSad 154f8cd48a3Schristos 15592ce8c6aSad int 156f8cd48a3Schristos elf_populate_auxv(struct lwp *l, struct exec_package *pack, char **stackp) 15792ce8c6aSad { 15892ce8c6aSad size_t len, vlen; 15992ce8c6aSad AuxInfo ai[ELF_AUX_ENTRIES], *a, *execname; 16092ce8c6aSad struct elf_args *ap; 161ae5efbe2Schristos char *path = l->l_proc->p_path; 16292ce8c6aSad int error; 16392ce8c6aSad 1640e8ea4cdSchristos execname = NULL; 16592ce8c6aSad a = ai; 16692ce8c6aSad 16706b89b30Smaxv memset(ai, 0, sizeof(ai)); 16806b89b30Smaxv 16992ce8c6aSad /* 17092ce8c6aSad * Push extra arguments on the stack needed by dynamically 17192ce8c6aSad * linked binaries 17292ce8c6aSad */ 17392ce8c6aSad if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 17492ce8c6aSad struct vattr *vap = pack->ep_vap; 17592ce8c6aSad 17692ce8c6aSad a->a_type = AT_PHDR; 17792ce8c6aSad a->a_v = ap->arg_phaddr; 17892ce8c6aSad a++; 17992ce8c6aSad 18092ce8c6aSad a->a_type = AT_PHENT; 18192ce8c6aSad a->a_v = ap->arg_phentsize; 18292ce8c6aSad a++; 18392ce8c6aSad 18492ce8c6aSad a->a_type = AT_PHNUM; 18592ce8c6aSad a->a_v = ap->arg_phnum; 18692ce8c6aSad a++; 18792ce8c6aSad 18892ce8c6aSad a->a_type = AT_PAGESZ; 18992ce8c6aSad a->a_v = PAGE_SIZE; 19092ce8c6aSad a++; 19192ce8c6aSad 19292ce8c6aSad a->a_type = AT_BASE; 19392ce8c6aSad a->a_v = ap->arg_interp; 19492ce8c6aSad a++; 19592ce8c6aSad 19692ce8c6aSad a->a_type = AT_FLAGS; 19792ce8c6aSad a->a_v = 0; 19892ce8c6aSad a++; 19992ce8c6aSad 20092ce8c6aSad a->a_type = AT_ENTRY; 20192ce8c6aSad a->a_v = ap->arg_entry; 20292ce8c6aSad a++; 20392ce8c6aSad 20421280b65Srin a->a_type = AT_STACKBASE; 20521280b65Srin a->a_v = l->l_proc->p_stackbase; 20621280b65Srin a++; 20721280b65Srin 20892ce8c6aSad a->a_type = AT_EUID; 20992ce8c6aSad if (vap->va_mode & S_ISUID) 21092ce8c6aSad a->a_v = vap->va_uid; 21192ce8c6aSad else 21292ce8c6aSad a->a_v = kauth_cred_geteuid(l->l_cred); 21392ce8c6aSad a++; 21492ce8c6aSad 21592ce8c6aSad a->a_type = AT_RUID; 21692ce8c6aSad a->a_v = kauth_cred_getuid(l->l_cred); 21792ce8c6aSad a++; 21892ce8c6aSad 21992ce8c6aSad a->a_type = AT_EGID; 22092ce8c6aSad if (vap->va_mode & S_ISGID) 22192ce8c6aSad a->a_v = vap->va_gid; 22292ce8c6aSad else 22392ce8c6aSad a->a_v = kauth_cred_getegid(l->l_cred); 22492ce8c6aSad a++; 22592ce8c6aSad 22692ce8c6aSad a->a_type = AT_RGID; 22792ce8c6aSad a->a_v = kauth_cred_getgid(l->l_cred); 22892ce8c6aSad a++; 22992ce8c6aSad 230ae5efbe2Schristos /* "/" means fexecve(2) could not resolve the pathname */ 231ae5efbe2Schristos if (path[0] == '/' && path[1] != '\0') { 23292ce8c6aSad execname = a; 23392ce8c6aSad a->a_type = AT_SUN_EXECNAME; 23492ce8c6aSad a++; 235ae5efbe2Schristos } 23692ce8c6aSad 2372210079eSmatt exec_free_emul_arg(pack); 23892ce8c6aSad } 23992ce8c6aSad 24092ce8c6aSad a->a_type = AT_NULL; 24192ce8c6aSad a->a_v = 0; 24292ce8c6aSad a++; 24392ce8c6aSad 244307c7101Sjoerg vlen = (a - ai) * sizeof(ai[0]); 245307c7101Sjoerg 246307c7101Sjoerg KASSERT(vlen <= sizeof(ai)); 24792ce8c6aSad 24837456883Schristos if (execname) { 24992ce8c6aSad execname->a_v = (uintptr_t)(*stackp + vlen); 25092ce8c6aSad len = strlen(path) + 1; 25192ce8c6aSad if ((error = copyout(path, (*stackp + vlen), len)) != 0) 25292ce8c6aSad return error; 25392ce8c6aSad len = ALIGN(len); 25437456883Schristos } else { 25537456883Schristos len = 0; 25637456883Schristos } 25792ce8c6aSad 25892ce8c6aSad if ((error = copyout(ai, *stackp, vlen)) != 0) 25992ce8c6aSad return error; 26092ce8c6aSad *stackp += vlen + len; 26192ce8c6aSad 26292ce8c6aSad return 0; 26392ce8c6aSad } 26492ce8c6aSad 26592ce8c6aSad /* 266f8cd48a3Schristos * Copy arguments onto the stack in the normal way, but add some 267f8cd48a3Schristos * extra information in case of dynamic binding. 268f8cd48a3Schristos */ 269f8cd48a3Schristos int 270f8cd48a3Schristos elf_copyargs(struct lwp *l, struct exec_package *pack, 271f8cd48a3Schristos struct ps_strings *arginfo, char **stackp, void *argp) 272f8cd48a3Schristos { 273f8cd48a3Schristos int error; 274f8cd48a3Schristos 275f8cd48a3Schristos if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) 276f8cd48a3Schristos return error; 277f8cd48a3Schristos 278f8cd48a3Schristos return elf_populate_auxv(l, pack, stackp); 279f8cd48a3Schristos } 280f8cd48a3Schristos 281f8cd48a3Schristos /* 28292ce8c6aSad * elf_check_header(): 28392ce8c6aSad * 28403ee7892Smartin * Check header for validity; return 0 if ok, ENOEXEC if error 28592ce8c6aSad */ 28692ce8c6aSad int 287c11747d0Smaxv elf_check_header(Elf_Ehdr *eh) 28892ce8c6aSad { 28992ce8c6aSad 29092ce8c6aSad if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 || 291406ea0abSchristos eh->e_ident[EI_CLASS] != ELFCLASS) { 29234e270cbSkamil DPRINTF("bad magic e_ident[EI_MAG0,EI_MAG3] %#x%x%x%x, " 29334e270cbSkamil "e_ident[EI_CLASS] %#x", eh->e_ident[EI_MAG0], 29434e270cbSkamil eh->e_ident[EI_MAG1], eh->e_ident[EI_MAG2], 29534e270cbSkamil eh->e_ident[EI_MAG3], eh->e_ident[EI_CLASS]); 296*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 297406ea0abSchristos } 29892ce8c6aSad 29992ce8c6aSad switch (eh->e_machine) { 30092ce8c6aSad 30192ce8c6aSad ELFDEFNNAME(MACHDEP_ID_CASES) 30292ce8c6aSad 30392ce8c6aSad default: 304406ea0abSchristos DPRINTF("bad machine %#x", eh->e_machine); 305*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 30692ce8c6aSad } 30792ce8c6aSad 308406ea0abSchristos if (ELF_EHDR_FLAGS_OK(eh) == 0) { 309406ea0abSchristos DPRINTF("bad flags %#x", eh->e_flags); 310*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 311406ea0abSchristos } 31292ce8c6aSad 313406ea0abSchristos if (eh->e_shnum > ELF_MAXSHNUM || eh->e_phnum > ELF_MAXPHNUM) { 314406ea0abSchristos DPRINTF("bad shnum/phnum %#x/%#x", eh->e_shnum, eh->e_phnum); 315*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 316406ea0abSchristos } 31792ce8c6aSad 31892ce8c6aSad return 0; 31992ce8c6aSad } 32092ce8c6aSad 32192ce8c6aSad /* 32292ce8c6aSad * elf_load_psection(): 32392ce8c6aSad * 32492ce8c6aSad * Load a psection at the appropriate address 32592ce8c6aSad */ 326109cfb32Schristos static int 32792ce8c6aSad elf_load_psection(struct exec_vmcmd_set *vcset, struct vnode *vp, 3287c099162Smaxv const Elf_Phdr *ph, Elf_Addr *addr, u_long *size, int flags) 32992ce8c6aSad { 33092ce8c6aSad u_long msize, psize, rm, rf; 33192ce8c6aSad long diff, offset; 3327c099162Smaxv int vmprot = 0; 33392ce8c6aSad 334f1ecb271Sad KASSERT(VOP_ISLOCKED(vp) != LK_NONE); 335f1ecb271Sad 33692ce8c6aSad /* 33792ce8c6aSad * If the user specified an address, then we load there. 33892ce8c6aSad */ 33992ce8c6aSad if (*addr == ELFDEFNNAME(NO_ADDR)) 34092ce8c6aSad *addr = ph->p_vaddr; 34192ce8c6aSad 34292ce8c6aSad if (ph->p_align > 1) { 34392ce8c6aSad /* 34492ce8c6aSad * Make sure we are virtually aligned as we are supposed to be. 34592ce8c6aSad */ 34692ce8c6aSad diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align); 347109cfb32Schristos if (*addr - diff != ELF_TRUNC(*addr, ph->p_align)) { 348109cfb32Schristos DPRINTF("bad alignment %#jx != %#jx\n", 349109cfb32Schristos (uintptr_t)(*addr - diff), 350109cfb32Schristos (uintptr_t)ELF_TRUNC(*addr, ph->p_align)); 351*b5090f27Sriastradh return SET_ERROR(EINVAL); 352109cfb32Schristos } 35392ce8c6aSad /* 35492ce8c6aSad * But make sure to not map any pages before the start of the 35592ce8c6aSad * psection by limiting the difference to within a page. 35692ce8c6aSad */ 35792ce8c6aSad diff &= PAGE_MASK; 35892ce8c6aSad } else 35992ce8c6aSad diff = 0; 36092ce8c6aSad 3617c099162Smaxv vmprot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0; 3627c099162Smaxv vmprot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0; 3637c099162Smaxv vmprot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0; 36492ce8c6aSad 36592ce8c6aSad /* 36692ce8c6aSad * Adjust everything so it all starts on a page boundary. 36792ce8c6aSad */ 36892ce8c6aSad *addr -= diff; 36992ce8c6aSad offset = ph->p_offset - diff; 37092ce8c6aSad *size = ph->p_filesz + diff; 37192ce8c6aSad msize = ph->p_memsz + diff; 37292ce8c6aSad 37392ce8c6aSad if (ph->p_align >= PAGE_SIZE) { 37492ce8c6aSad if ((ph->p_flags & PF_W) != 0) { 37592ce8c6aSad /* 37692ce8c6aSad * Because the pagedvn pager can't handle zero fill 37792ce8c6aSad * of the last data page if it's not page aligned we 37892ce8c6aSad * map the last page readvn. 37992ce8c6aSad */ 38092ce8c6aSad psize = trunc_page(*size); 38192ce8c6aSad } else { 38292ce8c6aSad psize = round_page(*size); 38392ce8c6aSad } 38492ce8c6aSad } else { 38592ce8c6aSad psize = *size; 38692ce8c6aSad } 38792ce8c6aSad 38892ce8c6aSad if (psize > 0) { 38992ce8c6aSad NEW_VMCMD2(vcset, ph->p_align < PAGE_SIZE ? 39092ce8c6aSad vmcmd_map_readvn : vmcmd_map_pagedvn, psize, *addr, vp, 3917c099162Smaxv offset, vmprot, flags); 39292ce8c6aSad flags &= VMCMD_RELATIVE; 39392ce8c6aSad } 39492ce8c6aSad if (psize < *size) { 39592ce8c6aSad NEW_VMCMD2(vcset, vmcmd_map_readvn, *size - psize, 3967c099162Smaxv *addr + psize, vp, offset + psize, vmprot, flags); 39792ce8c6aSad } 39892ce8c6aSad 39992ce8c6aSad /* 40092ce8c6aSad * Check if we need to extend the size of the segment (does 40192ce8c6aSad * bss extend page the next page boundary)? 40292ce8c6aSad */ 40392ce8c6aSad rm = round_page(*addr + msize); 40492ce8c6aSad rf = round_page(*addr + *size); 40592ce8c6aSad 40692ce8c6aSad if (rm != rf) { 40792ce8c6aSad NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 4087c099162Smaxv 0, vmprot, flags & VMCMD_RELATIVE); 40992ce8c6aSad *size = msize; 41092ce8c6aSad } 411109cfb32Schristos return 0; 41292ce8c6aSad } 41392ce8c6aSad 41492ce8c6aSad /* 415d8a274dfSmaxv * elf_load_interp(): 41692ce8c6aSad * 417d8a274dfSmaxv * Load an interpreter pointed to by path. 41892ce8c6aSad */ 41903cdabd0Smaxv static int 420d8a274dfSmaxv elf_load_interp(struct lwp *l, struct exec_package *epp, char *path, 42103cdabd0Smaxv struct exec_vmcmd_set *vcset, u_long *entryoff, Elf_Addr *last) 42292ce8c6aSad { 42392ce8c6aSad int error, i; 42492ce8c6aSad struct vnode *vp; 42592ce8c6aSad Elf_Ehdr eh; 42692ce8c6aSad Elf_Phdr *ph = NULL; 42792ce8c6aSad const Elf_Phdr *base_ph; 42892ce8c6aSad const Elf_Phdr *last_ph; 42992ce8c6aSad u_long phsize; 43092ce8c6aSad Elf_Addr addr = *last; 43192ce8c6aSad struct proc *p; 432f8c7c04bSmartin bool use_topdown; 43392ce8c6aSad 43492ce8c6aSad p = l->l_proc; 43592ce8c6aSad 43694b761b6Smartin KASSERT(p->p_vmspace); 43776713fa8Smartin KASSERT(p->p_vmspace != proc0.p_vmspace); 43876713fa8Smartin 439840bc630Schristos #ifdef __USE_TOPDOWN_VM 44041de4c61Smartin use_topdown = epp->ep_flags & EXEC_TOPDOWN_VM; 441f8c7c04bSmartin #else 442f8c7c04bSmartin use_topdown = false; 443f8c7c04bSmartin #endif 444f8c7c04bSmartin 44592ce8c6aSad /* 44692ce8c6aSad * 1. open file 44792ce8c6aSad * 2. read filehdr 44892ce8c6aSad * 3. map text, data, and bss out of it using VM_* 44992ce8c6aSad */ 45092ce8c6aSad vp = epp->ep_interp; 45192ce8c6aSad if (vp == NULL) { 45292ce8c6aSad error = emul_find_interp(l, epp, path); 45392ce8c6aSad if (error != 0) 45492ce8c6aSad return error; 45592ce8c6aSad vp = epp->ep_interp; 45692ce8c6aSad } 45792ce8c6aSad /* We'll tidy this ourselves - otherwise we have locking issues */ 45892ce8c6aSad epp->ep_interp = NULL; 459dd75e6d7Shannken vn_lock(vp, LK_SHARED | LK_RETRY); 46092ce8c6aSad 46192ce8c6aSad /* 46292ce8c6aSad * Similarly, if it's not marked as executable, or it's not a regular 46392ce8c6aSad * file, we don't allow it to be used. 46492ce8c6aSad */ 46592ce8c6aSad if (vp->v_type != VREG) { 466*b5090f27Sriastradh error = SET_ERROR(EACCES); 467f1ecb271Sad goto bad; 46892ce8c6aSad } 46992ce8c6aSad if ((error = VOP_ACCESS(vp, VEXEC, l->l_cred)) != 0) 470f1ecb271Sad goto bad; 47192ce8c6aSad 47292ce8c6aSad /* 47392ce8c6aSad * Check mount point. Though we're not trying to exec this binary, 47492ce8c6aSad * we will be executing code from it, so if the mount point 47592ce8c6aSad * disallows execution or set-id-ness, we punt or kill the set-id. 47692ce8c6aSad */ 47792ce8c6aSad if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 478*b5090f27Sriastradh error = SET_ERROR(EACCES); 479f1ecb271Sad goto bad; 48092ce8c6aSad } 48192ce8c6aSad if (vp->v_mount->mnt_flag & MNT_NOSUID) 48292ce8c6aSad epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID); 48392ce8c6aSad 48492ce8c6aSad error = vn_marktext(vp); 48592ce8c6aSad if (error) 486f1ecb271Sad goto bad; 48792ce8c6aSad 488f1ecb271Sad error = exec_read(l, vp, 0, &eh, sizeof(eh), IO_NODELOCKED); 489f1ecb271Sad if (error != 0) 49092ce8c6aSad goto bad; 49192ce8c6aSad 492c11747d0Smaxv if ((error = elf_check_header(&eh)) != 0) 49392ce8c6aSad goto bad; 494c11747d0Smaxv if (eh.e_type != ET_DYN || eh.e_phnum == 0) { 495406ea0abSchristos DPRINTF("bad interpreter type %#x", eh.e_type); 496*b5090f27Sriastradh error = SET_ERROR(ENOEXEC); 49792ce8c6aSad goto bad; 49892ce8c6aSad } 49992ce8c6aSad 50092ce8c6aSad phsize = eh.e_phnum * sizeof(Elf_Phdr); 50192ce8c6aSad ph = kmem_alloc(phsize, KM_SLEEP); 50292ce8c6aSad 503f1ecb271Sad error = exec_read(l, vp, eh.e_phoff, ph, phsize, IO_NODELOCKED); 504f1ecb271Sad if (error != 0) 50592ce8c6aSad goto bad; 50692ce8c6aSad 50792ce8c6aSad #ifdef ELF_INTERP_NON_RELOCATABLE 50892ce8c6aSad /* 50992ce8c6aSad * Evil hack: Only MIPS should be non-relocatable, and the 51092ce8c6aSad * psections should have a high address (typically 0x5ffe0000). 51192ce8c6aSad * If it's now relocatable, it should be linked at 0 and the 51292ce8c6aSad * psections should have zeros in the upper part of the address. 51392ce8c6aSad * Otherwise, force the load at the linked address. 51492ce8c6aSad */ 51592ce8c6aSad if (*last == ELF_LINK_ADDR && (ph->p_vaddr & 0xffff0000) == 0) 51692ce8c6aSad *last = ELFDEFNNAME(NO_ADDR); 51792ce8c6aSad #endif 51892ce8c6aSad 51992ce8c6aSad /* 52092ce8c6aSad * If no position to load the interpreter was set by a probe 52192ce8c6aSad * function, pick the same address that a non-fixed mmap(0, ..) 52292ce8c6aSad * would (i.e. something safely out of the way). 52392ce8c6aSad */ 52492ce8c6aSad if (*last == ELFDEFNNAME(NO_ADDR)) { 52592ce8c6aSad u_long limit = 0; 52692ce8c6aSad /* 52792ce8c6aSad * Find the start and ending addresses of the psections to 52892ce8c6aSad * be loaded. This will give us the size. 52992ce8c6aSad */ 53003cdabd0Smaxv for (i = 0, base_ph = NULL; i < eh.e_phnum; i++) { 53103cdabd0Smaxv if (ph[i].p_type == PT_LOAD) { 53203cdabd0Smaxv u_long psize = ph[i].p_vaddr + ph[i].p_memsz; 53392ce8c6aSad if (base_ph == NULL) 53403cdabd0Smaxv base_ph = &ph[i]; 53592ce8c6aSad if (psize > limit) 53692ce8c6aSad limit = psize; 53792ce8c6aSad } 53892ce8c6aSad } 53992ce8c6aSad 54092ce8c6aSad if (base_ph == NULL) { 541406ea0abSchristos DPRINTF("no interpreter loadable sections"); 542*b5090f27Sriastradh error = SET_ERROR(ENOEXEC); 54392ce8c6aSad goto bad; 54492ce8c6aSad } 54592ce8c6aSad 54692ce8c6aSad /* 54792ce8c6aSad * Now compute the size and load address. 54892ce8c6aSad */ 54992ce8c6aSad addr = (*epp->ep_esch->es_emul->e_vm_default_addr)(p, 55092ce8c6aSad epp->ep_daddr, 55176713fa8Smartin round_page(limit) - trunc_page(base_ph->p_vaddr), 55276713fa8Smartin use_topdown); 553cd1c56e8Schristos addr += (Elf_Addr)pax_aslr_rtld_offset(epp, base_ph->p_align, 554cd1c56e8Schristos use_topdown); 55576713fa8Smartin } else { 55692ce8c6aSad addr = *last; /* may be ELF_LINK_ADDR */ 55776713fa8Smartin } 55892ce8c6aSad 55992ce8c6aSad /* 56092ce8c6aSad * Load all the necessary sections 56192ce8c6aSad */ 56203cdabd0Smaxv for (i = 0, base_ph = NULL, last_ph = NULL; i < eh.e_phnum; i++) { 56303cdabd0Smaxv switch (ph[i].p_type) { 56492ce8c6aSad case PT_LOAD: { 56592ce8c6aSad u_long size; 56692ce8c6aSad int flags; 56792ce8c6aSad 56892ce8c6aSad if (base_ph == NULL) { 56992ce8c6aSad /* 57092ce8c6aSad * First encountered psection is always the 57192ce8c6aSad * base psection. Make sure it's aligned 57292ce8c6aSad * properly (align down for topdown and align 57392ce8c6aSad * upwards for not topdown). 57492ce8c6aSad */ 57503cdabd0Smaxv base_ph = &ph[i]; 57692ce8c6aSad flags = VMCMD_BASE; 57792ce8c6aSad if (addr == ELF_LINK_ADDR) 57803cdabd0Smaxv addr = ph[i].p_vaddr; 579f8c7c04bSmartin if (use_topdown) 58003cdabd0Smaxv addr = ELF_TRUNC(addr, ph[i].p_align); 58192ce8c6aSad else 58203cdabd0Smaxv addr = ELF_ROUND(addr, ph[i].p_align); 58392ce8c6aSad } else { 58492ce8c6aSad u_long limit = round_page(last_ph->p_vaddr 58592ce8c6aSad + last_ph->p_memsz); 58603cdabd0Smaxv u_long base = trunc_page(ph[i].p_vaddr); 58792ce8c6aSad 58892ce8c6aSad /* 58992ce8c6aSad * If there is a gap in between the psections, 59092ce8c6aSad * map it as inaccessible so nothing else 59192ce8c6aSad * mmap'ed will be placed there. 59292ce8c6aSad */ 59392ce8c6aSad if (limit != base) { 59492ce8c6aSad NEW_VMCMD2(vcset, vmcmd_map_zero, 59592ce8c6aSad base - limit, 59692ce8c6aSad limit - base_ph->p_vaddr, NULLVP, 59792ce8c6aSad 0, VM_PROT_NONE, VMCMD_RELATIVE); 59892ce8c6aSad } 59992ce8c6aSad 60003cdabd0Smaxv addr = ph[i].p_vaddr - base_ph->p_vaddr; 60192ce8c6aSad flags = VMCMD_RELATIVE; 60292ce8c6aSad } 60303cdabd0Smaxv last_ph = &ph[i]; 604109cfb32Schristos if ((error = elf_load_psection(vcset, vp, &ph[i], &addr, 605109cfb32Schristos &size, flags)) != 0) 606109cfb32Schristos goto bad; 60792ce8c6aSad /* 60892ce8c6aSad * If entry is within this psection then this 60992ce8c6aSad * must contain the .text section. *entryoff is 61092ce8c6aSad * relative to the base psection. 61192ce8c6aSad */ 61203cdabd0Smaxv if (eh.e_entry >= ph[i].p_vaddr && 61303cdabd0Smaxv eh.e_entry < (ph[i].p_vaddr + size)) { 61492ce8c6aSad *entryoff = eh.e_entry - base_ph->p_vaddr; 61592ce8c6aSad } 61692ce8c6aSad addr += size; 61792ce8c6aSad break; 61892ce8c6aSad } 61992ce8c6aSad 62092ce8c6aSad default: 62192ce8c6aSad break; 62292ce8c6aSad } 62392ce8c6aSad } 62492ce8c6aSad 62592ce8c6aSad kmem_free(ph, phsize); 62692ce8c6aSad /* 62792ce8c6aSad * This value is ignored if TOPDOWN. 62892ce8c6aSad */ 62992ce8c6aSad *last = addr; 630f1ecb271Sad vput(vp); 63192ce8c6aSad return 0; 63292ce8c6aSad 63392ce8c6aSad bad: 63492ce8c6aSad if (ph != NULL) 63592ce8c6aSad kmem_free(ph, phsize); 636f1ecb271Sad vput(vp); 63792ce8c6aSad return error; 63892ce8c6aSad } 63992ce8c6aSad 64092ce8c6aSad /* 64192ce8c6aSad * exec_elf_makecmds(): Prepare an Elf binary's exec package 64292ce8c6aSad * 64392ce8c6aSad * First, set of the various offsets/lengths in the exec package. 64492ce8c6aSad * 64592ce8c6aSad * Then, mark the text image busy (so it can be demand paged) or error 64692ce8c6aSad * out if this is not possible. Finally, set up vmcmds for the 64792ce8c6aSad * text, data, bss, and stack segments. 64892ce8c6aSad */ 64992ce8c6aSad int 65092ce8c6aSad exec_elf_makecmds(struct lwp *l, struct exec_package *epp) 65192ce8c6aSad { 65292ce8c6aSad Elf_Ehdr *eh = epp->ep_hdr; 65392ce8c6aSad Elf_Phdr *ph, *pp; 654590b9069Schs Elf_Addr phdr = 0, computed_phdr = 0, pos = 0, end_text = 0; 65503cdabd0Smaxv int error, i; 65692ce8c6aSad char *interp = NULL; 65792ce8c6aSad u_long phsize; 658d8a274dfSmaxv struct elf_args *ap; 659c11747d0Smaxv bool is_dyn = false; 66092ce8c6aSad 661406ea0abSchristos if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) { 662406ea0abSchristos DPRINTF("small header %#x", epp->ep_hdrvalid); 663*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 664406ea0abSchristos } 665c11747d0Smaxv if ((error = elf_check_header(eh)) != 0) 666c11747d0Smaxv return error; 66792ce8c6aSad 668c11747d0Smaxv if (eh->e_type == ET_DYN) 6696a1d6f07Smaxv /* PIE, and some libs have an entry point */ 670c11747d0Smaxv is_dyn = true; 671406ea0abSchristos else if (eh->e_type != ET_EXEC) { 672406ea0abSchristos DPRINTF("bad type %#x", eh->e_type); 673*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 674406ea0abSchristos } 67592ce8c6aSad 676406ea0abSchristos if (eh->e_phnum == 0) { 677406ea0abSchristos DPRINTF("no program headers"); 678*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 679406ea0abSchristos } 68092ce8c6aSad 681f1ecb271Sad /* XXX only LK_EXCLUSIVE to match all others - allow spinning */ 682f1ecb271Sad vn_lock(epp->ep_vp, LK_EXCLUSIVE | LK_RETRY); 68392ce8c6aSad error = vn_marktext(epp->ep_vp); 684f1ecb271Sad if (error) { 685f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 68692ce8c6aSad return error; 687f1ecb271Sad } 68892ce8c6aSad 68992ce8c6aSad /* 69092ce8c6aSad * Allocate space to hold all the program headers, and read them 69192ce8c6aSad * from the file 69292ce8c6aSad */ 69392ce8c6aSad phsize = eh->e_phnum * sizeof(Elf_Phdr); 69492ce8c6aSad ph = kmem_alloc(phsize, KM_SLEEP); 69592ce8c6aSad 696f1ecb271Sad error = exec_read(l, epp->ep_vp, eh->e_phoff, ph, phsize, 697f1ecb271Sad IO_NODELOCKED); 698f1ecb271Sad if (error != 0) { 699f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 70092ce8c6aSad goto bad; 701f1ecb271Sad } 70292ce8c6aSad 70392ce8c6aSad epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR); 70492ce8c6aSad epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR); 70592ce8c6aSad 70692ce8c6aSad for (i = 0; i < eh->e_phnum; i++) { 70792ce8c6aSad pp = &ph[i]; 70892ce8c6aSad if (pp->p_type == PT_INTERP) { 70939826d35Schristos if (pp->p_filesz < 2 || pp->p_filesz > MAXPATHLEN) { 710406ea0abSchristos DPRINTF("bad interpreter namelen %#jx", 711406ea0abSchristos (uintmax_t)pp->p_filesz); 712*b5090f27Sriastradh error = SET_ERROR(ENOEXEC); 713f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 71492ce8c6aSad goto bad; 71592ce8c6aSad } 71692ce8c6aSad interp = PNBUF_GET(); 717f1ecb271Sad error = exec_read(l, epp->ep_vp, pp->p_offset, interp, 718f1ecb271Sad pp->p_filesz, IO_NODELOCKED); 719f1ecb271Sad if (error != 0) { 720f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 72104e9e004Sskrll goto bad; 722f1ecb271Sad } 72339826d35Schristos /* Ensure interp is NUL-terminated and of the expected length */ 72439826d35Schristos if (strnlen(interp, pp->p_filesz) != pp->p_filesz - 1) { 725406ea0abSchristos DPRINTF("bad interpreter name"); 726*b5090f27Sriastradh error = SET_ERROR(ENOEXEC); 727f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 72839826d35Schristos goto bad; 72939826d35Schristos } 73092ce8c6aSad break; 73192ce8c6aSad } 73292ce8c6aSad } 73392ce8c6aSad 73492ce8c6aSad /* 73592ce8c6aSad * On the same architecture, we may be emulating different systems. 73692ce8c6aSad * See which one will accept this executable. 73792ce8c6aSad * 73892ce8c6aSad * Probe functions would normally see if the interpreter (if any) 73992ce8c6aSad * exists. Emulation packages may possibly replace the interpreter in 740b36a7fd2Smaxv * interp with a changed path (/emul/xxx/<path>). 74192ce8c6aSad */ 74292ce8c6aSad pos = ELFDEFNNAME(NO_ADDR); 74392ce8c6aSad if (epp->ep_esch->u.elf_probe_func) { 74492ce8c6aSad vaddr_t startp = (vaddr_t)pos; 74592ce8c6aSad 74692ce8c6aSad error = (*epp->ep_esch->u.elf_probe_func)(l, epp, eh, interp, 74792ce8c6aSad &startp); 748f1ecb271Sad if (error) { 749f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 75092ce8c6aSad goto bad; 751f1ecb271Sad } 75292ce8c6aSad pos = (Elf_Addr)startp; 75392ce8c6aSad } 75492ce8c6aSad 755f1ecb271Sad if (is_dyn && (error = elf_placedynexec(epp, eh, ph)) != 0) { 756f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 757109cfb32Schristos goto bad; 758f1ecb271Sad } 75992ce8c6aSad 76092ce8c6aSad /* 76192ce8c6aSad * Load all the necessary sections 76292ce8c6aSad */ 76303cdabd0Smaxv for (i = 0; i < eh->e_phnum; i++) { 76492ce8c6aSad Elf_Addr addr = ELFDEFNNAME(NO_ADDR); 76592ce8c6aSad u_long size = 0; 76692ce8c6aSad 76792ce8c6aSad switch (ph[i].p_type) { 76892ce8c6aSad case PT_LOAD: 769109cfb32Schristos if ((error = elf_load_psection(&epp->ep_vmcmds, 770109cfb32Schristos epp->ep_vp, &ph[i], &addr, &size, VMCMD_FIXED)) 771f1ecb271Sad != 0) { 772f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 773109cfb32Schristos goto bad; 774f1ecb271Sad } 77592ce8c6aSad 77692ce8c6aSad /* 777e84862bdSjoerg * Consider this as text segment, if it is executable. 778e84862bdSjoerg * If there is more than one text segment, pick the 779e84862bdSjoerg * largest. 78092ce8c6aSad */ 781e84862bdSjoerg if (ph[i].p_flags & PF_X) { 782e84862bdSjoerg if (epp->ep_taddr == ELFDEFNNAME(NO_ADDR) || 783e84862bdSjoerg size > epp->ep_tsize) { 78492ce8c6aSad epp->ep_taddr = addr; 78592ce8c6aSad epp->ep_tsize = size; 78692ce8c6aSad } 787b5e51c26Sjoerg end_text = addr + size; 78892ce8c6aSad } else { 78992ce8c6aSad epp->ep_daddr = addr; 79092ce8c6aSad epp->ep_dsize = size; 79192ce8c6aSad } 792590b9069Schs if (ph[i].p_offset == 0) { 793590b9069Schs computed_phdr = ph[i].p_vaddr + eh->e_phoff; 794590b9069Schs } 79592ce8c6aSad break; 79692ce8c6aSad 79792ce8c6aSad case PT_SHLIB: 79892ce8c6aSad /* SCO has these sections. */ 79992ce8c6aSad case PT_INTERP: 80092ce8c6aSad /* Already did this one. */ 80192ce8c6aSad case PT_DYNAMIC: 80292ce8c6aSad case PT_NOTE: 80392ce8c6aSad break; 80492ce8c6aSad case PT_PHDR: 80592ce8c6aSad /* Note address of program headers (in text segment) */ 80603cdabd0Smaxv phdr = ph[i].p_vaddr; 80792ce8c6aSad break; 80892ce8c6aSad 80992ce8c6aSad default: 81092ce8c6aSad /* 81192ce8c6aSad * Not fatal; we don't need to understand everything. 81292ce8c6aSad */ 81392ce8c6aSad break; 81492ce8c6aSad } 81592ce8c6aSad } 816c22b5e2aSmaxv 817f1ecb271Sad /* Now done with the vnode. */ 818f1ecb271Sad VOP_UNLOCK(epp->ep_vp); 819f1ecb271Sad 820477e684bSmaxv if (epp->ep_vmcmds.evs_used == 0) { 821c22b5e2aSmaxv /* No VMCMD; there was no PT_LOAD section, or those 822c22b5e2aSmaxv * sections were empty */ 823406ea0abSchristos DPRINTF("no vmcommands"); 824*b5090f27Sriastradh error = SET_ERROR(ENOEXEC); 825c22b5e2aSmaxv goto bad; 826c22b5e2aSmaxv } 827c22b5e2aSmaxv 828e84862bdSjoerg if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) { 82979f3dfffSchs epp->ep_daddr = round_page(end_text); 830b5e51c26Sjoerg epp->ep_dsize = 0; 831e84862bdSjoerg } 832e84862bdSjoerg 83392ce8c6aSad /* 83492ce8c6aSad * Check if we found a dynamically linked binary and arrange to load 83592ce8c6aSad * its interpreter 83692ce8c6aSad */ 83792ce8c6aSad if (interp) { 838d8a274dfSmaxv u_int nused = epp->ep_vmcmds.evs_used; 8396f9879baSchristos u_long interp_offset = 0; 84092ce8c6aSad 841d8a274dfSmaxv if ((error = elf_load_interp(l, epp, interp, 84203cdabd0Smaxv &epp->ep_vmcmds, &interp_offset, &pos)) != 0) { 84392ce8c6aSad goto bad; 84492ce8c6aSad } 845c22b5e2aSmaxv if (epp->ep_vmcmds.evs_used == nused) { 846d8a274dfSmaxv /* elf_load_interp() has not set up any new VMCMD */ 847406ea0abSchristos DPRINTF("no vmcommands for interpreter"); 848*b5090f27Sriastradh error = SET_ERROR(ENOEXEC); 849c22b5e2aSmaxv goto bad; 850c22b5e2aSmaxv } 851c22b5e2aSmaxv 852d8a274dfSmaxv ap = kmem_alloc(sizeof(*ap), KM_SLEEP); 853c22b5e2aSmaxv ap->arg_interp = epp->ep_vmcmds.evs_cmds[nused].ev_addr; 854ab77483fSmatt epp->ep_entryoffset = interp_offset; 85592ce8c6aSad epp->ep_entry = ap->arg_interp + interp_offset; 85692ce8c6aSad PNBUF_PUT(interp); 857856f192fSmaxv interp = NULL; 858d8a274dfSmaxv } else { 85992ce8c6aSad epp->ep_entry = eh->e_entry; 860bb321f61Schristos if (epp->ep_flags & EXEC_FORCEAUX) { 8613df3b581Schristos ap = kmem_zalloc(sizeof(*ap), KM_SLEEP); 862bb321f61Schristos ap->arg_interp = (vaddr_t)NULL; 8633df3b581Schristos } else { 864d8a274dfSmaxv ap = NULL; 865d8a274dfSmaxv } 8663df3b581Schristos } 86792ce8c6aSad 868590b9069Schs if (ap) { 869590b9069Schs ap->arg_phaddr = phdr ? phdr : computed_phdr; 870590b9069Schs ap->arg_phentsize = eh->e_phentsize; 871590b9069Schs ap->arg_phnum = eh->e_phnum; 872590b9069Schs ap->arg_entry = eh->e_entry; 873590b9069Schs epp->ep_emul_arg = ap; 8742210079eSmatt epp->ep_emul_arg_free = elf_free_emul_arg; 875590b9069Schs } 876590b9069Schs 87792ce8c6aSad #ifdef ELF_MAP_PAGE_ZERO 87892ce8c6aSad /* Dell SVR4 maps page zero, yeuch! */ 87992ce8c6aSad NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0, 88092ce8c6aSad epp->ep_vp, 0, VM_PROT_READ); 88192ce8c6aSad #endif 882856f192fSmaxv 883856f192fSmaxv error = (*epp->ep_esch->es_setup_stack)(l, epp); 884856f192fSmaxv if (error) 885856f192fSmaxv goto bad; 886856f192fSmaxv 88792ce8c6aSad kmem_free(ph, phsize); 888856f192fSmaxv return 0; 88992ce8c6aSad 89092ce8c6aSad bad: 89192ce8c6aSad if (interp) 89292ce8c6aSad PNBUF_PUT(interp); 8932210079eSmatt exec_free_emul_arg(epp); 89492ce8c6aSad kmem_free(ph, phsize); 89592ce8c6aSad kill_vmcmds(&epp->ep_vmcmds); 89692ce8c6aSad return error; 89792ce8c6aSad } 89892ce8c6aSad 89992ce8c6aSad int 90092ce8c6aSad netbsd_elf_signature(struct lwp *l, struct exec_package *epp, 90192ce8c6aSad Elf_Ehdr *eh) 90292ce8c6aSad { 90392ce8c6aSad size_t i; 90411594012Suwe Elf_Phdr *ph; 90511594012Suwe size_t phsize; 90611594012Suwe char *nbuf; 90792ce8c6aSad int error; 90892ce8c6aSad int isnetbsd = 0; 90911594012Suwe 91011594012Suwe epp->ep_pax_flags = 0; 91111594012Suwe 91211594012Suwe if (eh->e_phnum > ELF_MAXPHNUM || eh->e_phnum == 0) { 91311594012Suwe DPRINTF("no signature %#x", eh->e_phnum); 914*b5090f27Sriastradh return SET_ERROR(ENOEXEC); 91511594012Suwe } 91611594012Suwe 91711594012Suwe phsize = eh->e_phnum * sizeof(Elf_Phdr); 91811594012Suwe ph = kmem_alloc(phsize, KM_SLEEP); 919f1ecb271Sad error = exec_read(l, epp->ep_vp, eh->e_phoff, ph, phsize, 920f1ecb271Sad IO_NODELOCKED); 92111594012Suwe if (error) 92211594012Suwe goto out; 92311594012Suwe 92411594012Suwe nbuf = kmem_alloc(ELF_MAXNOTESIZE, KM_SLEEP); 92511594012Suwe for (i = 0; i < eh->e_phnum; i++) { 92611594012Suwe const char *nptr; 92711594012Suwe size_t nlen; 92811594012Suwe 92911594012Suwe if (ph[i].p_type != PT_NOTE || 93011594012Suwe ph[i].p_filesz > ELF_MAXNOTESIZE) 93111594012Suwe continue; 93211594012Suwe 93311594012Suwe nlen = ph[i].p_filesz; 934f1ecb271Sad error = exec_read(l, epp->ep_vp, ph[i].p_offset, nbuf, nlen, 935f1ecb271Sad IO_NODELOCKED); 93611594012Suwe if (error) 93711594012Suwe continue; 93811594012Suwe 93911594012Suwe nptr = nbuf; 94011594012Suwe while (nlen > 0) { 94111594012Suwe const Elf_Nhdr *np; 94211594012Suwe const char *ndata, *ndesc; 94311594012Suwe 94411594012Suwe /* note header */ 94511594012Suwe np = (const Elf_Nhdr *)nptr; 94611594012Suwe if (nlen < sizeof(*np)) { 94711594012Suwe break; 94811594012Suwe } 94911594012Suwe nptr += sizeof(*np); 95011594012Suwe nlen -= sizeof(*np); 95111594012Suwe 95211594012Suwe /* note name */ 95311594012Suwe ndata = nptr; 95411594012Suwe if (nlen < roundup(np->n_namesz, 4)) { 95511594012Suwe break; 95611594012Suwe } 95711594012Suwe nptr += roundup(np->n_namesz, 4); 95811594012Suwe nlen -= roundup(np->n_namesz, 4); 95911594012Suwe 96011594012Suwe /* note description */ 96111594012Suwe ndesc = nptr; 96211594012Suwe if (nlen < roundup(np->n_descsz, 4)) { 96311594012Suwe break; 96411594012Suwe } 96511594012Suwe nptr += roundup(np->n_descsz, 4); 96611594012Suwe nlen -= roundup(np->n_descsz, 4); 96711594012Suwe 96811594012Suwe isnetbsd |= netbsd_elf_note(epp, np, ndata, ndesc); 96911594012Suwe } 97011594012Suwe } 97111594012Suwe kmem_free(nbuf, ELF_MAXNOTESIZE); 97211594012Suwe 973*b5090f27Sriastradh error = isnetbsd ? 0 : SET_ERROR(ENOEXEC); 97411594012Suwe #ifdef DEBUG_ELF 97511594012Suwe if (error) 97611594012Suwe DPRINTF("not netbsd"); 97711594012Suwe #endif 97811594012Suwe out: 97911594012Suwe kmem_free(ph, phsize); 98011594012Suwe return error; 98111594012Suwe } 98211594012Suwe 98311594012Suwe int 98411594012Suwe netbsd_elf_note(struct exec_package *epp, 98511594012Suwe const Elf_Nhdr *np, const char *ndata, const char *ndesc) 98611594012Suwe { 98711594012Suwe int isnetbsd = 0; 98832d87f41Schristos 9897360fa83Schristos #ifdef DIAGNOSTIC 9907360fa83Schristos const char *badnote; 9917360fa83Schristos #define BADNOTE(n) badnote = (n) 9927360fa83Schristos #else 9937360fa83Schristos #define BADNOTE(n) 9947360fa83Schristos #endif 99592ce8c6aSad 99692ce8c6aSad switch (np->n_type) { 99792ce8c6aSad case ELF_NOTE_TYPE_NETBSD_TAG: 99833cfa4feSmaxv /* It is us */ 99995a363c9Schristos if (np->n_namesz == ELF_NOTE_NETBSD_NAMESZ && 100095a363c9Schristos np->n_descsz == ELF_NOTE_NETBSD_DESCSZ && 100192ce8c6aSad memcmp(ndata, ELF_NOTE_NETBSD_NAME, 100295a363c9Schristos ELF_NOTE_NETBSD_NAMESZ) == 0) { 1003ff3f3d5cSmaxv memcpy(&epp->ep_osversion, ndesc, 10041e90a44dSjoerg ELF_NOTE_NETBSD_DESCSZ); 100592ce8c6aSad isnetbsd = 1; 100692ce8c6aSad break; 100795a363c9Schristos } 100833cfa4feSmaxv 1009442d0c33Schristos /* 101041dca8abSchristos * Ignore SuSE tags; SuSE's n_type is the same the 101141dca8abSchristos * NetBSD one. 101295a363c9Schristos */ 101395a363c9Schristos if (np->n_namesz == ELF_NOTE_SUSE_NAMESZ && 101495a363c9Schristos memcmp(ndata, ELF_NOTE_SUSE_NAME, 101595a363c9Schristos ELF_NOTE_SUSE_NAMESZ) == 0) 101695a363c9Schristos break; 101741dca8abSchristos /* 101841dca8abSchristos * Ignore old GCC 101941dca8abSchristos */ 102041dca8abSchristos if (np->n_namesz == ELF_NOTE_OGCC_NAMESZ && 102141dca8abSchristos memcmp(ndata, ELF_NOTE_OGCC_NAME, 102241dca8abSchristos ELF_NOTE_OGCC_NAMESZ) == 0) 102341dca8abSchristos break; 10247360fa83Schristos BADNOTE("NetBSD tag"); 102595a363c9Schristos goto bad; 102695a363c9Schristos 102795a363c9Schristos case ELF_NOTE_TYPE_PAX_TAG: 102833cfa4feSmaxv if (np->n_namesz == ELF_NOTE_PAX_NAMESZ && 102933cfa4feSmaxv np->n_descsz == ELF_NOTE_PAX_DESCSZ && 103095a363c9Schristos memcmp(ndata, ELF_NOTE_PAX_NAME, 103133cfa4feSmaxv ELF_NOTE_PAX_NAMESZ) == 0) { 10329ed59591Smaxv uint32_t flags; 10339ed59591Smaxv memcpy(&flags, ndesc, sizeof(flags)); 10349ed59591Smaxv /* Convert the flags and insert them into 10359ed59591Smaxv * the exec package. */ 10369ed59591Smaxv pax_setup_elf_flags(epp, flags); 103733cfa4feSmaxv break; 103833cfa4feSmaxv } 10397360fa83Schristos BADNOTE("PaX tag"); 104033cfa4feSmaxv goto bad; 104133cfa4feSmaxv 104233cfa4feSmaxv case ELF_NOTE_TYPE_MARCH_TAG: 104333cfa4feSmaxv /* Copy the machine arch into the package. */ 104433cfa4feSmaxv if (np->n_namesz == ELF_NOTE_MARCH_NAMESZ 104533cfa4feSmaxv && memcmp(ndata, ELF_NOTE_MARCH_NAME, 104633cfa4feSmaxv ELF_NOTE_MARCH_NAMESZ) == 0) { 1047ff3f3d5cSmaxv /* Do not truncate the buffer */ 10487360fa83Schristos if (np->n_descsz > sizeof(epp->ep_machine_arch)) { 10497360fa83Schristos BADNOTE("description size limit"); 1050ff3f3d5cSmaxv goto bad; 10517360fa83Schristos } 1052ff3f3d5cSmaxv /* 1053ff3f3d5cSmaxv * Ensure ndesc is NUL-terminated and of the 1054ff3f3d5cSmaxv * expected length. 1055ff3f3d5cSmaxv */ 1056ff3f3d5cSmaxv if (strnlen(ndesc, np->n_descsz) + 1 != 10577360fa83Schristos np->n_descsz) { 10587360fa83Schristos BADNOTE("description size"); 1059ff3f3d5cSmaxv goto bad; 10607360fa83Schristos } 1061ff3f3d5cSmaxv strlcpy(epp->ep_machine_arch, ndesc, 106233cfa4feSmaxv sizeof(epp->ep_machine_arch)); 106333cfa4feSmaxv break; 106433cfa4feSmaxv } 10657360fa83Schristos BADNOTE("march tag"); 106633cfa4feSmaxv goto bad; 106733cfa4feSmaxv 106833cfa4feSmaxv case ELF_NOTE_TYPE_MCMODEL_TAG: 106933cfa4feSmaxv /* arch specific check for code model */ 107033cfa4feSmaxv #ifdef ELF_MD_MCMODEL_CHECK 107133cfa4feSmaxv if (np->n_namesz == ELF_NOTE_MCMODEL_NAMESZ 107233cfa4feSmaxv && memcmp(ndata, ELF_NOTE_MCMODEL_NAME, 107333cfa4feSmaxv ELF_NOTE_MCMODEL_NAMESZ) == 0) { 1074ff3f3d5cSmaxv ELF_MD_MCMODEL_CHECK(epp, ndesc, np->n_descsz); 107533cfa4feSmaxv break; 107633cfa4feSmaxv } 10777360fa83Schristos BADNOTE("mcmodel tag"); 107833cfa4feSmaxv goto bad; 107933cfa4feSmaxv #endif 108033cfa4feSmaxv break; 108133cfa4feSmaxv 108233cfa4feSmaxv case ELF_NOTE_TYPE_SUSE_VERSION_TAG: 108333cfa4feSmaxv break; 108433cfa4feSmaxv 1085f5789f4fSchristos case ELF_NOTE_TYPE_GO_BUILDID_TAG: 1086f5789f4fSchristos break; 1087f5789f4fSchristos 1088b858ac13Srin case ELF_NOTE_TYPE_FDO_PACKAGING_METADATA: 1089b858ac13Srin break; 1090b858ac13Srin 1091e9bf2ea4Schristos case ELF_NOTE_TYPE_NETBSD_EMUL_TAG: 1092e9bf2ea4Schristos /* Ancient NetBSD version tag */ 1093e9bf2ea4Schristos break; 1094e9bf2ea4Schristos 109533cfa4feSmaxv default: 10967360fa83Schristos BADNOTE("unknown tag"); 109795a363c9Schristos bad: 10983e2a63c7Schristos #ifdef DIAGNOSTIC 109933cfa4feSmaxv /* Ignore GNU tags */ 1100cf50f3a2Schristos if (np->n_namesz == ELF_NOTE_GNU_NAMESZ && 1101cf50f3a2Schristos memcmp(ndata, ELF_NOTE_GNU_NAME, 1102cf50f3a2Schristos ELF_NOTE_GNU_NAMESZ) == 0) 1103632a99a1Schristos break; 1104c14dea48Smaxv 110511594012Suwe int ns = (int)np->n_namesz; 11067360fa83Schristos printf("%s: Unknown elf note type %d (%s): " 11077360fa83Schristos "[namesz=%d, descsz=%d name=%-*.*s]\n", 11087360fa83Schristos epp->ep_kname, np->n_type, badnote, np->n_namesz, 110995a363c9Schristos np->n_descsz, ns, ns, ndata); 11103e2a63c7Schristos #endif 111192ce8c6aSad break; 111292ce8c6aSad } 111392ce8c6aSad 111411594012Suwe return isnetbsd; 111592ce8c6aSad } 111692ce8c6aSad 111792ce8c6aSad int 111892ce8c6aSad netbsd_elf_probe(struct lwp *l, struct exec_package *epp, void *eh, char *itp, 111992ce8c6aSad vaddr_t *pos) 112092ce8c6aSad { 112192ce8c6aSad int error; 112292ce8c6aSad 112392ce8c6aSad if ((error = netbsd_elf_signature(l, epp, eh)) != 0) 112492ce8c6aSad return error; 1125e110dba5Smatt #ifdef ELF_MD_PROBE_FUNC 1126e110dba5Smatt if ((error = ELF_MD_PROBE_FUNC(l, epp, eh, itp, pos)) != 0) 1127e110dba5Smatt return error; 1128e110dba5Smatt #elif defined(ELF_INTERP_NON_RELOCATABLE) 112992ce8c6aSad *pos = ELF_LINK_ADDR; 113092ce8c6aSad #endif 11315c3ccd6eSjoerg epp->ep_flags |= EXEC_FORCEAUX; 113292ce8c6aSad return 0; 113392ce8c6aSad } 11342210079eSmatt 11352210079eSmatt void 11362210079eSmatt elf_free_emul_arg(void *arg) 11372210079eSmatt { 11382210079eSmatt struct elf_args *ap = arg; 11392210079eSmatt KASSERT(ap != NULL); 11402210079eSmatt kmem_free(ap, sizeof(*ap)); 11412210079eSmatt } 1142