LCOV - code coverage report
Current view: top level - kern - exec_elf.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 575 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: exec_elf.c,v 1.146 2018/08/05 14:23:57 beck Exp $     */
       2             : 
       3             : /*
       4             :  * Copyright (c) 1996 Per Fogelstrom
       5             :  * All rights reserved.
       6             :  *
       7             :  * Copyright (c) 1994 Christos Zoulas
       8             :  * All rights reserved.
       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             :  * 3. The name of the author may not be used to endorse or promote products
      19             :  *    derived from this software without specific prior written permission
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      22             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      23             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      24             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      25             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      26             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      30             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  *
      32             :  */
      33             : 
      34             : /*
      35             :  * Copyright (c) 2001 Wasabi Systems, Inc.
      36             :  * All rights reserved.
      37             :  *
      38             :  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      39             :  *
      40             :  * Redistribution and use in source and binary forms, with or without
      41             :  * modification, are permitted provided that the following conditions
      42             :  * are met:
      43             :  * 1. Redistributions of source code must retain the above copyright
      44             :  *    notice, this list of conditions and the following disclaimer.
      45             :  * 2. Redistributions in binary form must reproduce the above copyright
      46             :  *    notice, this list of conditions and the following disclaimer in the
      47             :  *    documentation and/or other materials provided with the distribution.
      48             :  * 3. All advertising materials mentioning features or use of this software
      49             :  *    must display the following acknowledgement:
      50             :  *      This product includes software developed for the NetBSD Project by
      51             :  *      Wasabi Systems, Inc.
      52             :  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
      53             :  *    or promote products derived from this software without specific prior
      54             :  *    written permission.
      55             :  *
      56             :  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
      57             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      58             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      59             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
      60             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      61             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      62             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      63             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      64             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      65             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      66             :  * POSSIBILITY OF SUCH DAMAGE.
      67             :  */
      68             : 
      69             : #include <sys/param.h>
      70             : #include <sys/systm.h>
      71             : #include <sys/kernel.h>
      72             : #include <sys/proc.h>
      73             : #include <sys/malloc.h>
      74             : #include <sys/pool.h>
      75             : #include <sys/mount.h>
      76             : #include <sys/namei.h>
      77             : #include <sys/vnode.h>
      78             : #include <sys/core.h>
      79             : #include <sys/syslog.h>
      80             : #include <sys/exec.h>
      81             : #include <sys/exec_elf.h>
      82             : #include <sys/fcntl.h>
      83             : #include <sys/ptrace.h>
      84             : #include <sys/syscall.h>
      85             : #include <sys/signalvar.h>
      86             : #include <sys/stat.h>
      87             : #include <sys/pledge.h>
      88             : 
      89             : #include <sys/mman.h>
      90             : 
      91             : #include <uvm/uvm_extern.h>
      92             : 
      93             : #include <machine/reg.h>
      94             : #include <machine/exec.h>
      95             : 
      96             : int     elf_load_file(struct proc *, char *, struct exec_package *,
      97             :             struct elf_args *);
      98             : int     elf_check_header(Elf_Ehdr *);
      99             : int     elf_read_from(struct proc *, struct vnode *, u_long, void *, int);
     100             : void    elf_load_psection(struct exec_vmcmd_set *, struct vnode *,
     101             :             Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int);
     102             : int     coredump_elf(struct proc *, void *);
     103             : void    *elf_copyargs(struct exec_package *, struct ps_strings *, void *,
     104             :             void *);
     105             : int     exec_elf_fixup(struct proc *, struct exec_package *);
     106             : int     elf_os_pt_note(struct proc *, struct exec_package *, Elf_Ehdr *,
     107             :             char *, size_t, size_t);
     108             : 
     109             : extern char sigcode[], esigcode[], sigcoderet[];
     110             : #ifdef SYSCALL_DEBUG
     111             : extern char *syscallnames[];
     112             : #endif
     113             : 
     114             : /* round up and down to page boundaries. */
     115             : #define ELF_ROUND(a, b)         (((a) + (b) - 1) & ~((b) - 1))
     116             : #define ELF_TRUNC(a, b)         ((a) & ~((b) - 1))
     117             : 
     118             : /*
     119             :  * We limit the number of program headers to 32, this should
     120             :  * be a reasonable limit for ELF, the most we have seen so far is 12
     121             :  */
     122             : #define ELF_MAX_VALID_PHDR 32
     123             : 
     124             : /*
     125             :  * How many entries are in the AuxInfo array we pass to the process?
     126             :  */
     127             : #define ELF_AUX_ENTRIES 8
     128             : 
     129             : /*
     130             :  * This is the OpenBSD ELF emul
     131             :  */
     132             : struct emul emul_elf = {
     133             :         "native",
     134             :         NULL,
     135             :         SYS_syscall,
     136             :         SYS_MAXSYSCALL,
     137             :         sysent,
     138             : #ifdef SYSCALL_DEBUG
     139             :         syscallnames,
     140             : #else
     141             :         NULL,
     142             : #endif
     143             :         (sizeof(AuxInfo) * ELF_AUX_ENTRIES / sizeof(char *)),
     144             :         elf_copyargs,
     145             :         setregs,
     146             :         exec_elf_fixup,
     147             :         coredump_elf,
     148             :         sigcode,
     149             :         esigcode,
     150             :         sigcoderet
     151             : };
     152             : 
     153             : /*
     154             :  * Copy arguments onto the stack in the normal way, but add some
     155             :  * space for extra information in case of dynamic binding.
     156             :  */
     157             : void *
     158           0 : elf_copyargs(struct exec_package *pack, struct ps_strings *arginfo,
     159             :                 void *stack, void *argp)
     160             : {
     161           0 :         stack = copyargs(pack, arginfo, stack, argp);
     162           0 :         if (!stack)
     163           0 :                 return (NULL);
     164             : 
     165             :         /*
     166             :          * Push space for extra arguments on the stack needed by
     167             :          * dynamically linked binaries.
     168             :          */
     169           0 :         if (pack->ep_emul_arg != NULL) {
     170           0 :                 pack->ep_emul_argp = stack;
     171           0 :                 stack = (char *)stack + ELF_AUX_ENTRIES * sizeof (AuxInfo);
     172           0 :         }
     173           0 :         return (stack);
     174           0 : }
     175             : 
     176             : /*
     177             :  * Check header for validity; return 0 for ok, ENOEXEC if error
     178             :  */
     179             : int
     180           0 : elf_check_header(Elf_Ehdr *ehdr)
     181             : {
     182             :         /*
     183             :          * We need to check magic, class size, endianess, and version before
     184             :          * we look at the rest of the Elf_Ehdr structure. These few elements
     185             :          * are represented in a machine independent fashion.
     186             :          */
     187           0 :         if (!IS_ELF(*ehdr) ||
     188           0 :             ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
     189           0 :             ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
     190           0 :             ehdr->e_ident[EI_VERSION] != ELF_TARG_VER)
     191           0 :                 return (ENOEXEC);
     192             : 
     193             :         /* Now check the machine dependent header */
     194           0 :         if (ehdr->e_machine != ELF_TARG_MACH ||
     195           0 :             ehdr->e_version != ELF_TARG_VER)
     196           0 :                 return (ENOEXEC);
     197             : 
     198             :         /* Don't allow an insane amount of sections. */
     199           0 :         if (ehdr->e_phnum > ELF_MAX_VALID_PHDR)
     200           0 :                 return (ENOEXEC);
     201             : 
     202           0 :         return (0);
     203           0 : }
     204             : 
     205             : /*
     206             :  * Load a psection at the appropriate address
     207             :  */
     208             : void
     209           0 : elf_load_psection(struct exec_vmcmd_set *vcset, struct vnode *vp,
     210             :     Elf_Phdr *ph, Elf_Addr *addr, Elf_Addr *size, int *prot, int flags)
     211             : {
     212             :         u_long msize, lsize, psize, rm, rf;
     213             :         long diff, offset, bdiff;
     214             :         Elf_Addr base;
     215             : 
     216             :         /*
     217             :          * If the user specified an address, then we load there.
     218             :          */
     219           0 :         if (*addr != ELF_NO_ADDR) {
     220           0 :                 if (ph->p_align > 1) {
     221           0 :                         *addr = ELF_TRUNC(*addr, ph->p_align);
     222           0 :                         diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align);
     223             :                         /* page align vaddr */
     224           0 :                         base = *addr + trunc_page(ph->p_vaddr) 
     225           0 :                             - ELF_TRUNC(ph->p_vaddr, ph->p_align);
     226           0 :                 } else {
     227             :                         diff = 0;
     228           0 :                         base = *addr + trunc_page(ph->p_vaddr) - ph->p_vaddr;
     229             :                 }
     230             :         } else {
     231           0 :                 *addr = ph->p_vaddr;
     232           0 :                 if (ph->p_align > 1)
     233           0 :                         *addr = ELF_TRUNC(*addr, ph->p_align);
     234           0 :                 base = trunc_page(ph->p_vaddr);
     235           0 :                 diff = ph->p_vaddr - *addr;
     236             :         }
     237           0 :         bdiff = ph->p_vaddr - trunc_page(ph->p_vaddr);
     238             : 
     239             :         /*
     240             :          * Enforce W^X and map W|X segments without X permission
     241             :          * initially.  The dynamic linker will make these read-only
     242             :          * and add back X permission after relocation processing.
     243             :          * Static executables with W|X segments will probably crash.
     244             :          */
     245           0 :         *prot |= (ph->p_flags & PF_R) ? PROT_READ : 0;
     246           0 :         *prot |= (ph->p_flags & PF_W) ? PROT_WRITE : 0;
     247           0 :         if ((ph->p_flags & PF_W) == 0)
     248           0 :                 *prot |= (ph->p_flags & PF_X) ? PROT_EXEC : 0;
     249             : 
     250           0 :         msize = ph->p_memsz + diff;
     251           0 :         offset = ph->p_offset - bdiff;
     252           0 :         lsize = ph->p_filesz + bdiff;
     253           0 :         psize = round_page(lsize);
     254             : 
     255             :         /*
     256             :          * Because the pagedvn pager can't handle zero fill of the last
     257             :          * data page if it's not page aligned we map the last page readvn.
     258             :          */
     259           0 :         if (ph->p_flags & PF_W) {
     260           0 :                 psize = trunc_page(lsize);
     261           0 :                 if (psize > 0)
     262           0 :                         NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp,
     263             :                             offset, *prot, flags);
     264           0 :                 if (psize != lsize) {
     265           0 :                         NEW_VMCMD2(vcset, vmcmd_map_readvn, lsize - psize,
     266             :                             base + psize, vp, offset + psize, *prot, flags);
     267           0 :                 }
     268             :         } else {
     269           0 :                 NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp, offset,
     270             :                     *prot, flags);
     271             :         }
     272             : 
     273             :         /*
     274             :          * Check if we need to extend the size of the segment
     275             :          */
     276           0 :         rm = round_page(*addr + ph->p_memsz + diff);
     277           0 :         rf = round_page(*addr + ph->p_filesz + diff);
     278             : 
     279           0 :         if (rm != rf) {
     280           0 :                 NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0,
     281             :                     *prot, flags);
     282           0 :         }
     283           0 :         *size = msize;
     284           0 : }
     285             : 
     286             : /*
     287             :  * Read from vnode into buffer at offset.
     288             :  */
     289             : int
     290           0 : elf_read_from(struct proc *p, struct vnode *vp, u_long off, void *buf,
     291             :     int size)
     292             : {
     293             :         int error;
     294           0 :         size_t resid;
     295             : 
     296           0 :         if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE,
     297           0 :             0, p->p_ucred, &resid, p)) != 0)
     298           0 :                 return error;
     299             :         /*
     300             :          * See if we got all of it
     301             :          */
     302           0 :         if (resid != 0)
     303           0 :                 return (ENOEXEC);
     304           0 :         return (0);
     305           0 : }
     306             : 
     307             : /*
     308             :  * Load a file (interpreter/library) pointed to by path [stolen from
     309             :  * coff_load_shlib()]. Made slightly generic so it might be used externally.
     310             :  */
     311             : int
     312           0 : elf_load_file(struct proc *p, char *path, struct exec_package *epp,
     313             :     struct elf_args *ap)
     314             : {
     315             :         int error, i;
     316           0 :         struct nameidata nd;
     317           0 :         Elf_Ehdr eh;
     318             :         Elf_Phdr *ph = NULL;
     319             :         u_long phsize = 0;
     320           0 :         Elf_Addr addr;
     321             :         struct vnode *vp;
     322             :         Elf_Phdr *base_ph = NULL;
     323           0 :         struct interp_ld_sec {
     324             :                 Elf_Addr vaddr;
     325             :                 u_long memsz;
     326             :         } loadmap[ELF_MAX_VALID_PHDR];
     327             :         int nload, idx = 0;
     328             :         Elf_Addr pos;
     329             :         int file_align;
     330             :         int loop;
     331             :         size_t randomizequota = ELF_RANDOMIZE_LIMIT;
     332             : 
     333           0 :         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
     334           0 :         nd.ni_pledge = PLEDGE_RPATH;
     335           0 :         nd.ni_unveil = UNVEIL_READ;
     336           0 :         if ((error = namei(&nd)) != 0) {
     337           0 :                 return (error);
     338             :         }
     339           0 :         vp = nd.ni_vp;
     340           0 :         if (vp->v_type != VREG) {
     341             :                 error = EACCES;
     342           0 :                 goto bad;
     343             :         }
     344           0 :         if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0)
     345             :                 goto bad;
     346           0 :         if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
     347             :                 error = EACCES;
     348           0 :                 goto bad;
     349             :         }
     350           0 :         if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0)
     351             :                 goto bad1;
     352           0 :         if ((error = elf_read_from(p, nd.ni_vp, 0, &eh, sizeof(eh))) != 0)
     353             :                 goto bad1;
     354             : 
     355           0 :         if (elf_check_header(&eh) || eh.e_type != ET_DYN) {
     356             :                 error = ENOEXEC;
     357           0 :                 goto bad1;
     358             :         }
     359             : 
     360           0 :         ph = mallocarray(eh.e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK);
     361           0 :         phsize = eh.e_phnum * sizeof(Elf_Phdr);
     362             : 
     363           0 :         if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff, ph, phsize)) != 0)
     364             :                 goto bad1;
     365             : 
     366           0 :         for (i = 0; i < eh.e_phnum; i++) {
     367           0 :                 if (ph[i].p_type == PT_LOAD) {
     368           0 :                         if (ph[i].p_filesz > ph[i].p_memsz ||
     369           0 :                             ph[i].p_memsz == 0) {
     370             :                                 error = EINVAL;
     371           0 :                                 goto bad1;
     372             :                         }
     373           0 :                         loadmap[idx].vaddr = trunc_page(ph[i].p_vaddr);
     374           0 :                         loadmap[idx].memsz = round_page (ph[i].p_vaddr +
     375             :                             ph[i].p_memsz - loadmap[idx].vaddr);
     376           0 :                         file_align = ph[i].p_align;
     377           0 :                         idx++;
     378           0 :                 }
     379             :         }
     380             :         nload = idx;
     381             : 
     382             :         /*
     383             :          * Load the interpreter where a non-fixed mmap(NULL, ...)
     384             :          * would (i.e. something safely out of the way).
     385             :          */
     386           0 :         pos = uvm_map_hint(p->p_vmspace, PROT_EXEC, VM_MIN_ADDRESS,
     387             :             VM_MAXUSER_ADDRESS);
     388           0 :         pos = ELF_ROUND(pos, file_align);
     389             : 
     390             :         loop = 0;
     391           0 :         for (i = 0; i < nload;/**/) {
     392           0 :                 vaddr_t addr;
     393             :                 struct  uvm_object *uobj;
     394             :                 off_t   uoff;
     395             :                 size_t  size;
     396             : 
     397             : #ifdef this_needs_fixing
     398             :                 if (i == 0) {
     399             :                         uobj = &vp->v_uvm.u_obj;
     400             :                         /* need to fix uoff */
     401             :                 } else {
     402             : #endif
     403             :                         uobj = NULL;
     404             :                         uoff = 0;
     405             : #ifdef this_needs_fixing
     406             :                 }
     407             : #endif
     408             : 
     409           0 :                 addr = trunc_page(pos + loadmap[i].vaddr);
     410           0 :                 size =  round_page(addr + loadmap[i].memsz) - addr;
     411             : 
     412             :                 /* CRAP - map_findspace does not avoid daddr+BRKSIZ */
     413           0 :                 if ((addr + size > (vaddr_t)p->p_vmspace->vm_daddr) &&
     414           0 :                     (addr < (vaddr_t)p->p_vmspace->vm_daddr + BRKSIZ))
     415           0 :                         addr = round_page((vaddr_t)p->p_vmspace->vm_daddr +
     416             :                             BRKSIZ);
     417             : 
     418           0 :                 if (uvm_map_mquery(&p->p_vmspace->vm_map, &addr, size,
     419           0 :                     (i == 0 ? uoff : UVM_UNKNOWN_OFFSET), 0) != 0) {
     420           0 :                         if (loop == 0) {
     421             :                                 loop = 1;
     422             :                                 i = 0;
     423             :                                 pos = 0;
     424           0 :                                 continue;
     425             :                         }
     426             :                         error = ENOMEM;
     427           0 :                         goto bad1;
     428             :                 }
     429           0 :                 if (addr != pos + loadmap[i].vaddr) {
     430             :                         /* base changed. */
     431           0 :                         pos = addr - trunc_page(loadmap[i].vaddr);
     432           0 :                         pos = ELF_ROUND(pos,file_align);
     433             :                         i = 0;
     434           0 :                         continue;
     435             :                 }
     436             : 
     437           0 :                 i++;
     438           0 :         }
     439             : 
     440             :         /*
     441             :          * Load all the necessary sections
     442             :          */
     443           0 :         for (i = 0; i < eh.e_phnum; i++) {
     444           0 :                 Elf_Addr size = 0;
     445           0 :                 int prot = 0;
     446             :                 int flags;
     447             : 
     448           0 :                 switch (ph[i].p_type) {
     449             :                 case PT_LOAD:
     450           0 :                         if (base_ph == NULL) {
     451             :                                 flags = VMCMD_BASE;
     452           0 :                                 addr = pos;
     453             :                                 base_ph = &ph[i];
     454           0 :                         } else {
     455             :                                 flags = VMCMD_RELATIVE;
     456           0 :                                 addr = ph[i].p_vaddr - base_ph->p_vaddr;
     457             :                         }
     458           0 :                         elf_load_psection(&epp->ep_vmcmds, nd.ni_vp,
     459             :                             &ph[i], &addr, &size, &prot, flags);
     460             :                         /* If entry is within this section it must be text */
     461           0 :                         if (eh.e_entry >= ph[i].p_vaddr &&
     462           0 :                             eh.e_entry < (ph[i].p_vaddr + size)) {
     463           0 :                                 epp->ep_entry = addr + eh.e_entry -
     464           0 :                                     ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align);
     465           0 :                                 if (flags == VMCMD_RELATIVE)
     466           0 :                                         epp->ep_entry += pos;
     467           0 :                                 ap->arg_interp = pos;
     468           0 :                         }
     469           0 :                         addr += size;
     470           0 :                         break;
     471             : 
     472             :                 case PT_DYNAMIC:
     473             :                 case PT_PHDR:
     474             :                 case PT_NOTE:
     475             :                         break;
     476             : 
     477             :                 case PT_OPENBSD_RANDOMIZE:
     478           0 :                         if (ph[i].p_memsz > randomizequota) {
     479             :                                 error = ENOMEM;
     480           0 :                                 goto bad1;
     481             :                         }
     482           0 :                         randomizequota -= ph[i].p_memsz;
     483           0 :                         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize,
     484             :                             ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0);
     485           0 :                         break;
     486             : 
     487             :                 default:
     488             :                         break;
     489             :                 }
     490           0 :         }
     491             : 
     492           0 :         vn_marktext(nd.ni_vp);
     493             : 
     494             : bad1:
     495           0 :         VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p);
     496             : bad:
     497           0 :         free(ph, M_TEMP, phsize);
     498             : 
     499           0 :         vput(nd.ni_vp);
     500           0 :         return (error);
     501           0 : }
     502             : 
     503             : /*
     504             :  * Prepare an Elf binary's exec package
     505             :  *
     506             :  * First, set of the various offsets/lengths in the exec package.
     507             :  *
     508             :  * Then, mark the text image busy (so it can be demand paged) or error out if
     509             :  * this is not possible.  Finally, set up vmcmds for the text, data, bss, and
     510             :  * stack segments.
     511             :  */
     512             : int
     513           0 : exec_elf_makecmds(struct proc *p, struct exec_package *epp)
     514             : {
     515           0 :         Elf_Ehdr *eh = epp->ep_hdr;
     516             :         Elf_Phdr *ph, *pp, *base_ph = NULL;
     517             :         Elf_Addr phdr = 0, exe_base = 0;
     518             :         int error, i, has_phdr = 0;
     519             :         char *interp = NULL;
     520             :         u_long phsize;
     521             :         size_t randomizequota = ELF_RANDOMIZE_LIMIT;
     522             : 
     523           0 :         if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
     524           0 :                 return (ENOEXEC);
     525             : 
     526           0 :         if (elf_check_header(eh) ||
     527           0 :            (eh->e_type != ET_EXEC && eh->e_type != ET_DYN))
     528           0 :                 return (ENOEXEC);
     529             : 
     530             :         /*
     531             :          * check if vnode is in open for writing, because we want to demand-
     532             :          * page out of it.  if it is, don't do it, for various reasons.
     533             :          */
     534           0 :         if (epp->ep_vp->v_writecount != 0) {
     535             : #ifdef DIAGNOSTIC
     536           0 :                 if (epp->ep_vp->v_flag & VTEXT)
     537           0 :                         panic("exec: a VTEXT vnode has writecount != 0");
     538             : #endif
     539           0 :                 return (ETXTBSY);
     540             :         }
     541             :         /*
     542             :          * Allocate space to hold all the program headers, and read them
     543             :          * from the file
     544             :          */
     545           0 :         ph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK);
     546           0 :         phsize = eh->e_phnum * sizeof(Elf_Phdr);
     547             : 
     548           0 :         if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff, ph,
     549           0 :             phsize)) != 0)
     550             :                 goto bad;
     551             : 
     552           0 :         epp->ep_tsize = ELF_NO_ADDR;
     553           0 :         epp->ep_dsize = ELF_NO_ADDR;
     554             : 
     555           0 :         for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
     556           0 :                 if (pp->p_type == PT_INTERP && !interp) {
     557           0 :                         if (pp->p_filesz < 2 || pp->p_filesz > MAXPATHLEN)
     558             :                                 goto bad;
     559           0 :                         interp = pool_get(&namei_pool, PR_WAITOK);
     560           0 :                         if ((error = elf_read_from(p, epp->ep_vp,
     561           0 :                             pp->p_offset, interp, pp->p_filesz)) != 0) {
     562             :                                 goto bad;
     563             :                         }
     564           0 :                         if (interp[pp->p_filesz - 1] != '\0')
     565             :                                 goto bad;
     566           0 :                 } else if (pp->p_type == PT_LOAD) {
     567           0 :                         if (pp->p_filesz > pp->p_memsz ||
     568           0 :                             pp->p_memsz == 0) {
     569             :                                 error = EINVAL;
     570           0 :                                 goto bad;
     571             :                         }
     572           0 :                         if (base_ph == NULL)
     573           0 :                                 base_ph = pp;
     574           0 :                 } else if (pp->p_type == PT_PHDR) {
     575             :                         has_phdr = 1;
     576           0 :                 }
     577             :         }
     578             : 
     579           0 :         if (eh->e_type == ET_DYN) {
     580             :                 /* need phdr and load sections for PIE */
     581           0 :                 if (!has_phdr || base_ph == NULL) {
     582             :                         error = EINVAL;
     583           0 :                         goto bad;
     584             :                 }
     585             :                 /* randomize exe_base for PIE */
     586           0 :                 exe_base = uvm_map_pie(base_ph->p_align);
     587           0 :         }
     588             : 
     589             :         /*
     590             :          * OK, we want a slightly different twist of the
     591             :          * standard emulation package for "real" elf.
     592             :          */
     593           0 :         epp->ep_emul = &emul_elf;
     594             : 
     595             :         /*
     596             :          * Verify this is an OpenBSD executable.  If it's marked that way
     597             :          * via a PT_NOTE then also check for a PT_OPENBSD_WXNEEDED segment.
     598             :          */
     599           0 :         if (eh->e_ident[EI_OSABI] != ELFOSABI_OPENBSD && (error =
     600           0 :             elf_os_pt_note(p, epp, epp->ep_hdr, "OpenBSD", 8, 4)) != 0) {
     601             :                 goto bad;
     602             :         }
     603             : 
     604             :         /*
     605             :          * Load all the necessary sections
     606             :          */
     607           0 :         for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
     608           0 :                 Elf_Addr addr, size = 0;
     609           0 :                 int prot = 0;
     610             :                 int flags = 0;
     611             : 
     612           0 :                 switch (pp->p_type) {
     613             :                 case PT_LOAD:
     614           0 :                         if (exe_base != 0) {
     615           0 :                                 if (pp == base_ph) {
     616             :                                         flags = VMCMD_BASE;
     617           0 :                                         addr = exe_base;
     618           0 :                                 } else {
     619             :                                         flags = VMCMD_RELATIVE;
     620           0 :                                         addr = pp->p_vaddr - base_ph->p_vaddr;
     621             :                                 }
     622             :                         } else
     623           0 :                                 addr = ELF_NO_ADDR;
     624             : 
     625             :                         /*
     626             :                          * Calculates size of text and data segments
     627             :                          * by starting at first and going to end of last.
     628             :                          * 'rwx' sections are treated as data.
     629             :                          * this is correct for BSS_PLT, but may not be
     630             :                          * for DATA_PLT, is fine for TEXT_PLT.
     631             :                          */
     632           0 :                         elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
     633             :                             pp, &addr, &size, &prot, flags);
     634             : 
     635             :                         /*
     636             :                          * Update exe_base in case alignment was off.
     637             :                          * For PIE, addr is relative to exe_base so
     638             :                          * adjust it (non PIE exe_base is 0 so no change).
     639             :                          */
     640           0 :                         if (flags == VMCMD_BASE)
     641           0 :                                 exe_base = addr;
     642             :                         else
     643           0 :                                 addr += exe_base;
     644             : 
     645             :                         /*
     646             :                          * Decide whether it's text or data by looking
     647             :                          * at the protection of the section
     648             :                          */
     649           0 :                         if (prot & PROT_WRITE) {
     650             :                                 /* data section */
     651           0 :                                 if (epp->ep_dsize == ELF_NO_ADDR) {
     652           0 :                                         epp->ep_daddr = addr;
     653           0 :                                         epp->ep_dsize = size;
     654           0 :                                 } else {
     655           0 :                                         if (addr < epp->ep_daddr) {
     656           0 :                                                 epp->ep_dsize =
     657           0 :                                                     epp->ep_dsize +
     658           0 :                                                     epp->ep_daddr -
     659             :                                                     addr;
     660           0 :                                                 epp->ep_daddr = addr;
     661           0 :                                         } else
     662           0 :                                                 epp->ep_dsize = addr+size -
     663             :                                                     epp->ep_daddr;
     664             :                                 }
     665           0 :                         } else if (prot & PROT_EXEC) {
     666             :                                 /* text section */
     667           0 :                                 if (epp->ep_tsize == ELF_NO_ADDR) {
     668           0 :                                         epp->ep_taddr = addr;
     669           0 :                                         epp->ep_tsize = size;
     670           0 :                                 } else {
     671           0 :                                         if (addr < epp->ep_taddr) {
     672           0 :                                                 epp->ep_tsize =
     673           0 :                                                     epp->ep_tsize +
     674           0 :                                                     epp->ep_taddr -
     675             :                                                     addr;
     676           0 :                                                 epp->ep_taddr = addr;
     677           0 :                                         } else
     678           0 :                                                 epp->ep_tsize = addr+size -
     679             :                                                     epp->ep_taddr;
     680             :                                 }
     681             :                         }
     682             :                         break;
     683             : 
     684             :                 case PT_SHLIB:
     685             :                         error = ENOEXEC;
     686           0 :                         goto bad;
     687             : 
     688             :                 case PT_INTERP:
     689             :                         /* Already did this one */
     690             :                 case PT_DYNAMIC:
     691             :                 case PT_NOTE:
     692             :                         break;
     693             : 
     694             :                 case PT_PHDR:
     695             :                         /* Note address of program headers (in text segment) */
     696           0 :                         phdr = pp->p_vaddr;
     697           0 :                         break;
     698             : 
     699             :                 case PT_OPENBSD_RANDOMIZE:
     700           0 :                         if (ph[i].p_memsz > randomizequota) {
     701             :                                 error = ENOMEM;
     702           0 :                                 goto bad;
     703             :                         }
     704           0 :                         randomizequota -= ph[i].p_memsz;
     705           0 :                         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize,
     706             :                             ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0, 0);
     707           0 :                         break;
     708             : 
     709             :                 default:
     710             :                         /*
     711             :                          * Not fatal, we don't need to understand everything
     712             :                          * :-)
     713             :                          */
     714             :                         break;
     715             :                 }
     716           0 :         }
     717             : 
     718           0 :         phdr += exe_base;
     719             : 
     720             :         /*
     721             :          * Strangely some linux programs may have all load sections marked
     722             :          * writeable, in this case, textsize is not -1, but rather 0;
     723             :          */
     724           0 :         if (epp->ep_tsize == ELF_NO_ADDR)
     725           0 :                 epp->ep_tsize = 0;
     726             :         /*
     727             :          * Another possibility is that it has all load sections marked
     728             :          * read-only.  Fake a zero-sized data segment right after the
     729             :          * text segment.
     730             :          */
     731           0 :         if (epp->ep_dsize == ELF_NO_ADDR) {
     732           0 :                 epp->ep_daddr = round_page(epp->ep_taddr + epp->ep_tsize);
     733           0 :                 epp->ep_dsize = 0;
     734           0 :         }
     735             : 
     736           0 :         epp->ep_interp = interp;
     737           0 :         epp->ep_entry = eh->e_entry + exe_base;
     738             : 
     739             :         /*
     740             :          * Check if we found a dynamically linked binary and arrange to load
     741             :          * its interpreter when the exec file is released.
     742             :          */
     743           0 :         if (interp || eh->e_type == ET_DYN) {
     744             :                 struct elf_args *ap;
     745             : 
     746           0 :                 ap = malloc(sizeof(*ap), M_TEMP, M_WAITOK);
     747             : 
     748           0 :                 ap->arg_phaddr = phdr;
     749           0 :                 ap->arg_phentsize = eh->e_phentsize;
     750           0 :                 ap->arg_phnum = eh->e_phnum;
     751           0 :                 ap->arg_entry = eh->e_entry + exe_base;
     752           0 :                 ap->arg_interp = exe_base;
     753             : 
     754           0 :                 epp->ep_emul_arg = ap;
     755           0 :                 epp->ep_emul_argsize = sizeof *ap;
     756           0 :         }
     757             : 
     758           0 :         free(ph, M_TEMP, phsize);
     759           0 :         vn_marktext(epp->ep_vp);
     760           0 :         return (exec_setup_stack(p, epp));
     761             : 
     762             : bad:
     763           0 :         if (interp)
     764           0 :                 pool_put(&namei_pool, interp);
     765           0 :         free(ph, M_TEMP, phsize);
     766           0 :         kill_vmcmds(&epp->ep_vmcmds);
     767           0 :         if (error == 0)
     768           0 :                 return (ENOEXEC);
     769           0 :         return (error);
     770           0 : }
     771             : 
     772             : /*
     773             :  * Phase II of load. It is now safe to load the interpreter. Info collected
     774             :  * when loading the program is available for setup of the interpreter.
     775             :  */
     776             : int
     777           0 : exec_elf_fixup(struct proc *p, struct exec_package *epp)
     778             : {
     779             :         char    *interp;
     780             :         int     error = 0;
     781             :         struct  elf_args *ap;
     782           0 :         AuxInfo ai[ELF_AUX_ENTRIES], *a;
     783             : 
     784           0 :         if (epp->ep_emul_arg == NULL) {
     785           0 :                 return (0);
     786             :         }
     787             : 
     788           0 :         interp = epp->ep_interp;
     789           0 :         ap = epp->ep_emul_arg;
     790             : 
     791           0 :         if (interp &&
     792           0 :             (error = elf_load_file(p, interp, epp, ap)) != 0) {
     793           0 :                 free(ap, M_TEMP, epp->ep_emul_argsize);
     794           0 :                 pool_put(&namei_pool, interp);
     795           0 :                 kill_vmcmds(&epp->ep_vmcmds);
     796           0 :                 return (error);
     797             :         }
     798             :         /*
     799             :          * We have to do this ourselves...
     800             :          */
     801           0 :         error = exec_process_vmcmds(p, epp);
     802             : 
     803             :         /*
     804             :          * Push extra arguments on the stack needed by dynamically
     805             :          * linked binaries
     806             :          */
     807           0 :         if (error == 0) {
     808           0 :                 memset(&ai, 0, sizeof ai);
     809           0 :                 a = ai;
     810             : 
     811           0 :                 a->au_id = AUX_phdr;
     812           0 :                 a->au_v = ap->arg_phaddr;
     813           0 :                 a++;
     814             : 
     815           0 :                 a->au_id = AUX_phent;
     816           0 :                 a->au_v = ap->arg_phentsize;
     817           0 :                 a++;
     818             : 
     819           0 :                 a->au_id = AUX_phnum;
     820           0 :                 a->au_v = ap->arg_phnum;
     821           0 :                 a++;
     822             : 
     823           0 :                 a->au_id = AUX_pagesz;
     824           0 :                 a->au_v = PAGE_SIZE;
     825           0 :                 a++;
     826             : 
     827           0 :                 a->au_id = AUX_base;
     828           0 :                 a->au_v = ap->arg_interp;
     829           0 :                 a++;
     830             : 
     831           0 :                 a->au_id = AUX_flags;
     832           0 :                 a->au_v = 0;
     833           0 :                 a++;
     834             : 
     835           0 :                 a->au_id = AUX_entry;
     836           0 :                 a->au_v = ap->arg_entry;
     837           0 :                 a++;
     838             : 
     839           0 :                 a->au_id = AUX_null;
     840           0 :                 a->au_v = 0;
     841             :                 a++;
     842             : 
     843           0 :                 error = copyout(ai, epp->ep_emul_argp, sizeof ai);
     844           0 :         }
     845           0 :         free(ap, M_TEMP, epp->ep_emul_argsize);
     846           0 :         if (interp)
     847           0 :                 pool_put(&namei_pool, interp);
     848           0 :         return (error);
     849           0 : }
     850             : 
     851             : int
     852           0 : elf_os_pt_note(struct proc *p, struct exec_package *epp, Elf_Ehdr *eh,
     853             :     char *os_name, size_t name_size, size_t desc_size)
     854             : {
     855           0 :         char pathbuf[MAXPATHLEN];
     856             :         Elf_Phdr *hph, *ph;
     857             :         Elf_Note *np = NULL;
     858             :         size_t phsize;
     859             :         int error;
     860             : 
     861           0 :         hph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK);
     862           0 :         phsize = eh->e_phnum * sizeof(Elf_Phdr);
     863           0 :         if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff,
     864           0 :             hph, phsize)) != 0)
     865             :                 goto out1;
     866             : 
     867           0 :         for (ph = hph;  ph < &hph[eh->e_phnum]; ph++) {
     868           0 :                 if (ph->p_type == PT_OPENBSD_WXNEEDED) {
     869           0 :                         int wxallowed = (epp->ep_vp->v_mount &&
     870           0 :                             (epp->ep_vp->v_mount->mnt_flag & MNT_WXALLOWED));
     871             :                         
     872           0 :                         if (!wxallowed) {
     873           0 :                                 error = copyinstr(epp->ep_name, &pathbuf,
     874             :                                     sizeof(pathbuf), NULL);
     875           0 :                                 log(LOG_NOTICE,
     876             :                                     "%s(%d): W^X binary outside wxallowed mountpoint\n",
     877           0 :                                     error ? "" : pathbuf, p->p_p->ps_pid);
     878             :                                 error = EACCES;
     879           0 :                                 goto out1;
     880             :                         }
     881           0 :                         epp->ep_flags |= EXEC_WXNEEDED;
     882           0 :                         break;
     883             :                 }
     884             :         }
     885             : 
     886           0 :         for (ph = hph;  ph < &hph[eh->e_phnum]; ph++) {
     887           0 :                 if (ph->p_type != PT_NOTE ||
     888           0 :                     ph->p_filesz > 1024 ||
     889           0 :                     ph->p_filesz < sizeof(Elf_Note) + name_size)
     890             :                         continue;
     891             : 
     892           0 :                 np = malloc(ph->p_filesz, M_TEMP, M_WAITOK);
     893           0 :                 if ((error = elf_read_from(p, epp->ep_vp, ph->p_offset,
     894           0 :                     np, ph->p_filesz)) != 0)
     895             :                         goto out2;
     896             : 
     897             : #if 0
     898             :                 if (np->type != ELF_NOTE_TYPE_OSVERSION) {
     899             :                         free(np, M_TEMP, ph->p_filesz);
     900             :                         np = NULL;
     901             :                         continue;
     902             :                 }
     903             : #endif
     904             : 
     905             :                 /* Check the name and description sizes. */
     906           0 :                 if (np->namesz != name_size ||
     907           0 :                     np->descsz != desc_size)
     908             :                         goto out3;
     909             : 
     910           0 :                 if (memcmp((np + 1), os_name, name_size))
     911             :                         goto out3;
     912             : 
     913             :                 /* XXX: We could check for the specific emulation here */
     914             :                 /* All checks succeeded. */
     915             :                 error = 0;
     916           0 :                 goto out2;
     917             :         }
     918             : 
     919             : out3:
     920           0 :         error = ENOEXEC;
     921             : out2:
     922           0 :         free(np, M_TEMP, ph->p_filesz);
     923             : out1:
     924           0 :         free(hph, M_TEMP, phsize);
     925           0 :         return error;
     926           0 : }
     927             : 
     928             : /*
     929             :  * Start of routines related to dumping core
     930             :  */
     931             : 
     932             : #ifdef SMALL_KERNEL
     933             : int
     934             : coredump_elf(struct proc *p, void *cookie)
     935             : {
     936             :         return EPERM;
     937             : }
     938             : #else /* !SMALL_KERNEL */
     939             : 
     940             : struct writesegs_state {
     941             :         off_t   notestart;
     942             :         off_t   secstart;
     943             :         off_t   secoff;
     944             :         struct  proc *p;
     945             :         void    *iocookie;
     946             :         Elf_Phdr *psections;
     947             :         size_t  psectionslen;
     948             :         size_t  notesize;
     949             :         int     npsections;
     950             : };
     951             : 
     952             : uvm_coredump_setup_cb   coredump_setup_elf;
     953             : uvm_coredump_walk_cb    coredump_walk_elf;
     954             : 
     955             : int     coredump_notes_elf(struct proc *, void *, size_t *);
     956             : int     coredump_note_elf(struct proc *, void *, size_t *);
     957             : int     coredump_writenote_elf(struct proc *, void *, Elf_Note *,
     958             :             const char *, void *);
     959             : 
     960             : #define ELFROUNDSIZE    4       /* XXX Should it be sizeof(Elf_Word)? */
     961             : #define elfround(x)     roundup((x), ELFROUNDSIZE)
     962             : 
     963             : int
     964           0 : coredump_elf(struct proc *p, void *cookie)
     965             : {
     966             : #ifdef DIAGNOSTIC
     967             :         off_t offset;
     968             : #endif
     969           0 :         struct writesegs_state ws;
     970           0 :         size_t notesize;
     971             :         int error, i;
     972             : 
     973           0 :         ws.p = p;
     974           0 :         ws.iocookie = cookie;
     975           0 :         ws.psections = NULL;
     976             : 
     977             :         /*
     978             :          * Walk the map to get all the segment offsets and lengths,
     979             :          * write out the ELF header.
     980             :          */
     981           0 :         error = uvm_coredump_walkmap(p, coredump_setup_elf,
     982             :             coredump_walk_elf, &ws);
     983           0 :         if (error)
     984             :                 goto out;
     985             : 
     986           0 :         error = coredump_write(cookie, UIO_SYSSPACE, ws.psections,
     987           0 :             ws.psectionslen);
     988           0 :         if (error)
     989             :                 goto out;
     990             : 
     991             :         /* Write out the notes. */
     992           0 :         error = coredump_notes_elf(p, cookie, &notesize);
     993           0 :         if (error)
     994             :                 goto out;
     995             : 
     996             : #ifdef DIAGNOSTIC
     997           0 :         if (notesize != ws.notesize)
     998           0 :                 panic("coredump: notesize changed: %zu != %zu",
     999             :                     ws.notesize, notesize);
    1000           0 :         offset = ws.notestart + notesize;
    1001           0 :         if (offset != ws.secstart)
    1002           0 :                 panic("coredump: offset %lld != secstart %lld",
    1003             :                     (long long) offset, (long long) ws.secstart);
    1004             : #endif
    1005             : 
    1006             :         /* Pass 3: finally, write the sections themselves. */
    1007           0 :         for (i = 0; i < ws.npsections - 1; i++) {
    1008           0 :                 Elf_Phdr *pent = &ws.psections[i];
    1009           0 :                 if (pent->p_filesz == 0)
    1010           0 :                         continue;
    1011             : 
    1012             : #ifdef DIAGNOSTIC
    1013           0 :                 if (offset != pent->p_offset)
    1014           0 :                         panic("coredump: offset %lld != p_offset[%d] %lld",
    1015             :                             (long long) offset, i,
    1016             :                             (long long) pent->p_filesz);
    1017             : #endif
    1018             : 
    1019           0 :                 error = coredump_write(cookie, UIO_USERSPACE,
    1020           0 :                     (void *)(vaddr_t)pent->p_vaddr, pent->p_filesz);
    1021           0 :                 if (error)
    1022           0 :                         goto out;
    1023             : 
    1024           0 :                 coredump_unmap(cookie, (vaddr_t)pent->p_vaddr,
    1025           0 :                     (vaddr_t)pent->p_vaddr + pent->p_filesz);
    1026             : 
    1027             : #ifdef DIAGNOSTIC
    1028           0 :                 offset += ws.psections[i].p_filesz;
    1029             : #endif
    1030           0 :         }
    1031             : 
    1032             : out:
    1033           0 :         free(ws.psections, M_TEMP, ws.psectionslen);
    1034           0 :         return (error);
    1035           0 : }
    1036             : 
    1037             : 
    1038             : 
    1039             : int
    1040           0 : coredump_setup_elf(int segment_count, void *cookie)
    1041             : {
    1042           0 :         Elf_Ehdr ehdr;
    1043           0 :         struct writesegs_state *ws = cookie;
    1044             :         Elf_Phdr *note;
    1045             :         int error;
    1046             : 
    1047             :         /* Get the count of segments, plus one for the PT_NOTE */
    1048           0 :         ws->npsections = segment_count + 1;
    1049             : 
    1050             :         /* Get the size of the notes. */
    1051           0 :         error = coredump_notes_elf(ws->p, NULL, &ws->notesize);
    1052           0 :         if (error)
    1053           0 :                 return error;
    1054             : 
    1055             :         /* Setup the ELF header */
    1056           0 :         memset(&ehdr, 0, sizeof(ehdr));
    1057           0 :         memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
    1058           0 :         ehdr.e_ident[EI_CLASS] = ELF_TARG_CLASS;
    1059           0 :         ehdr.e_ident[EI_DATA] = ELF_TARG_DATA;
    1060           0 :         ehdr.e_ident[EI_VERSION] = EV_CURRENT;
    1061             :         /* XXX Should be the OSABI/ABI version of the executable. */
    1062           0 :         ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
    1063           0 :         ehdr.e_ident[EI_ABIVERSION] = 0;
    1064           0 :         ehdr.e_type = ET_CORE;
    1065             :         /* XXX This should be the e_machine of the executable. */
    1066           0 :         ehdr.e_machine = ELF_TARG_MACH;
    1067           0 :         ehdr.e_version = EV_CURRENT;
    1068           0 :         ehdr.e_entry = 0;
    1069           0 :         ehdr.e_phoff = sizeof(ehdr);
    1070           0 :         ehdr.e_shoff = 0;
    1071           0 :         ehdr.e_flags = 0;
    1072           0 :         ehdr.e_ehsize = sizeof(ehdr);
    1073           0 :         ehdr.e_phentsize = sizeof(Elf_Phdr);
    1074           0 :         ehdr.e_phnum = ws->npsections;
    1075           0 :         ehdr.e_shentsize = 0;
    1076           0 :         ehdr.e_shnum = 0;
    1077           0 :         ehdr.e_shstrndx = 0;
    1078             : 
    1079             :         /* Write out the ELF header. */
    1080           0 :         error = coredump_write(ws->iocookie, UIO_SYSSPACE, &ehdr, sizeof(ehdr));
    1081           0 :         if (error)
    1082           0 :                 return error;
    1083             : 
    1084             :         /*
    1085             :          * Allocate the segment header array and setup to collect
    1086             :          * the section sizes and offsets
    1087             :          */
    1088           0 :         ws->psections = mallocarray(ws->npsections, sizeof(Elf_Phdr),
    1089             :             M_TEMP, M_WAITOK|M_ZERO);
    1090           0 :         ws->psectionslen = ws->npsections * sizeof(Elf_Phdr);
    1091             : 
    1092           0 :         ws->notestart = sizeof(ehdr) + ws->psectionslen;
    1093           0 :         ws->secstart = ws->notestart + ws->notesize;
    1094           0 :         ws->secoff = ws->secstart;
    1095             : 
    1096             :         /* Fill in the PT_NOTE segment header in the last slot */
    1097           0 :         note = &ws->psections[ws->npsections - 1];
    1098           0 :         note->p_type = PT_NOTE;
    1099           0 :         note->p_offset = ws->notestart;
    1100           0 :         note->p_vaddr = 0;
    1101           0 :         note->p_paddr = 0;
    1102           0 :         note->p_filesz = ws->notesize;
    1103           0 :         note->p_memsz = 0;
    1104           0 :         note->p_flags = PF_R;
    1105           0 :         note->p_align = ELFROUNDSIZE;
    1106             : 
    1107           0 :         return (0);
    1108           0 : }
    1109             : 
    1110             : int
    1111           0 : coredump_walk_elf(vaddr_t start, vaddr_t realend, vaddr_t end, vm_prot_t prot,
    1112             :     int nsegment, void *cookie)
    1113             : {
    1114           0 :         struct writesegs_state *ws = cookie;
    1115             :         Elf_Phdr phdr;
    1116             :         vsize_t size, realsize;
    1117             : 
    1118           0 :         size = end - start;
    1119           0 :         realsize = realend - start;
    1120             : 
    1121             :         phdr.p_type = PT_LOAD;
    1122           0 :         phdr.p_offset = ws->secoff;
    1123             :         phdr.p_vaddr = start;
    1124             :         phdr.p_paddr = 0;
    1125             :         phdr.p_filesz = realsize;
    1126             :         phdr.p_memsz = size;
    1127             :         phdr.p_flags = 0;
    1128           0 :         if (prot & PROT_READ)
    1129           0 :                 phdr.p_flags |= PF_R;
    1130           0 :         if (prot & PROT_WRITE)
    1131           0 :                 phdr.p_flags |= PF_W;
    1132           0 :         if (prot & PROT_EXEC)
    1133           0 :                 phdr.p_flags |= PF_X;
    1134             :         phdr.p_align = PAGE_SIZE;
    1135             : 
    1136           0 :         ws->secoff += phdr.p_filesz;
    1137           0 :         ws->psections[nsegment] = phdr;
    1138             : 
    1139           0 :         return (0);
    1140             : }
    1141             : 
    1142             : int
    1143           0 : coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep)
    1144             : {
    1145           0 :         struct ps_strings pss;
    1146           0 :         struct iovec iov;
    1147           0 :         struct uio uio;
    1148           0 :         struct elfcore_procinfo cpi;
    1149           0 :         Elf_Note nhdr;
    1150           0 :         struct process *pr = p->p_p;
    1151             :         struct proc *q;
    1152           0 :         size_t size, notesize;
    1153             :         int error;
    1154             : 
    1155             :         size = 0;
    1156             : 
    1157             :         /* First, write an elfcore_procinfo. */
    1158           0 :         notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
    1159             :             elfround(sizeof(cpi));
    1160           0 :         if (iocookie) {
    1161           0 :                 memset(&cpi, 0, sizeof(cpi));
    1162             : 
    1163           0 :                 cpi.cpi_version = ELFCORE_PROCINFO_VERSION;
    1164           0 :                 cpi.cpi_cpisize = sizeof(cpi);
    1165           0 :                 cpi.cpi_signo = p->p_sisig;
    1166           0 :                 cpi.cpi_sigcode = p->p_sicode;
    1167             : 
    1168           0 :                 cpi.cpi_sigpend = p->p_siglist;
    1169           0 :                 cpi.cpi_sigmask = p->p_sigmask;
    1170           0 :                 cpi.cpi_sigignore = pr->ps_sigacts->ps_sigignore;
    1171           0 :                 cpi.cpi_sigcatch = pr->ps_sigacts->ps_sigcatch;
    1172             : 
    1173           0 :                 cpi.cpi_pid = pr->ps_pid;
    1174           0 :                 cpi.cpi_ppid = pr->ps_pptr->ps_pid;
    1175           0 :                 cpi.cpi_pgrp = pr->ps_pgid;
    1176           0 :                 if (pr->ps_session->s_leader)
    1177           0 :                         cpi.cpi_sid = pr->ps_session->s_leader->ps_pid;
    1178             :                 else
    1179           0 :                         cpi.cpi_sid = 0;
    1180             : 
    1181           0 :                 cpi.cpi_ruid = p->p_ucred->cr_ruid;
    1182           0 :                 cpi.cpi_euid = p->p_ucred->cr_uid;
    1183           0 :                 cpi.cpi_svuid = p->p_ucred->cr_svuid;
    1184             : 
    1185           0 :                 cpi.cpi_rgid = p->p_ucred->cr_rgid;
    1186           0 :                 cpi.cpi_egid = p->p_ucred->cr_gid;
    1187           0 :                 cpi.cpi_svgid = p->p_ucred->cr_svgid;
    1188             : 
    1189           0 :                 (void)strlcpy(cpi.cpi_name, pr->ps_comm, sizeof(cpi.cpi_name));
    1190             : 
    1191           0 :                 nhdr.namesz = sizeof("OpenBSD");
    1192           0 :                 nhdr.descsz = sizeof(cpi);
    1193           0 :                 nhdr.type = NT_OPENBSD_PROCINFO;
    1194             : 
    1195           0 :                 error = coredump_writenote_elf(p, iocookie, &nhdr,
    1196             :                     "OpenBSD", &cpi);
    1197           0 :                 if (error)
    1198           0 :                         return (error);
    1199             :         }
    1200           0 :         size += notesize;
    1201             : 
    1202             :         /* Second, write an NT_OPENBSD_AUXV note. */
    1203           0 :         notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
    1204           0 :             elfround(pr->ps_emul->e_arglen * sizeof(char *));
    1205           0 :         if (iocookie) {
    1206           0 :                 iov.iov_base = &pss;
    1207           0 :                 iov.iov_len = sizeof(pss);
    1208           0 :                 uio.uio_iov = &iov;
    1209           0 :                 uio.uio_iovcnt = 1;
    1210           0 :                 uio.uio_offset = (off_t)pr->ps_strings;
    1211           0 :                 uio.uio_resid = sizeof(pss);
    1212           0 :                 uio.uio_segflg = UIO_SYSSPACE;
    1213           0 :                 uio.uio_rw = UIO_READ;
    1214           0 :                 uio.uio_procp = NULL;
    1215             : 
    1216           0 :                 error = uvm_io(&p->p_vmspace->vm_map, &uio, 0);
    1217           0 :                 if (error)
    1218           0 :                         return (error);
    1219             : 
    1220           0 :                 if (pss.ps_envstr == NULL)
    1221           0 :                         return (EIO);
    1222             : 
    1223           0 :                 nhdr.namesz = sizeof("OpenBSD");
    1224           0 :                 nhdr.descsz = pr->ps_emul->e_arglen * sizeof(char *);
    1225           0 :                 nhdr.type = NT_OPENBSD_AUXV;
    1226             : 
    1227           0 :                 error = coredump_write(iocookie, UIO_SYSSPACE,
    1228             :                     &nhdr, sizeof(nhdr));
    1229           0 :                 if (error)
    1230           0 :                         return (error);
    1231             : 
    1232           0 :                 error = coredump_write(iocookie, UIO_SYSSPACE,
    1233           0 :                     "OpenBSD", elfround(nhdr.namesz));
    1234           0 :                 if (error)
    1235           0 :                         return (error);
    1236             : 
    1237           0 :                 error = coredump_write(iocookie, UIO_USERSPACE,
    1238           0 :                     pss.ps_envstr + pss.ps_nenvstr + 1, nhdr.descsz);
    1239           0 :                 if (error)
    1240           0 :                         return (error);
    1241             :         }
    1242           0 :         size += notesize;
    1243             : 
    1244             : #ifdef PT_WCOOKIE
    1245             :         notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
    1246             :             elfround(sizeof(register_t));
    1247             :         if (iocookie) {
    1248             :                 register_t wcookie;
    1249             : 
    1250             :                 nhdr.namesz = sizeof("OpenBSD");
    1251             :                 nhdr.descsz = sizeof(register_t);
    1252             :                 nhdr.type = NT_OPENBSD_WCOOKIE;
    1253             : 
    1254             :                 wcookie = process_get_wcookie(p);
    1255             :                 error = coredump_writenote_elf(p, iocookie, &nhdr,
    1256             :                     "OpenBSD", &wcookie);
    1257             :                 if (error)
    1258             :                         return (error);
    1259             :         }
    1260             :         size += notesize;
    1261             : #endif
    1262             : 
    1263             :         /*
    1264             :          * Now write the register info for the thread that caused the
    1265             :          * coredump.
    1266             :          */
    1267           0 :         error = coredump_note_elf(p, iocookie, &notesize);
    1268           0 :         if (error)
    1269           0 :                 return (error);
    1270           0 :         size += notesize;
    1271             : 
    1272             :         /*
    1273             :          * Now, for each thread, write the register info and any other
    1274             :          * per-thread notes.  Since we're dumping core, all the other
    1275             :          * threads in the process have been stopped and the list can't
    1276             :          * change.
    1277             :          */
    1278           0 :         TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) {
    1279           0 :                 if (q == p)             /* we've taken care of this thread */
    1280             :                         continue;
    1281           0 :                 error = coredump_note_elf(q, iocookie, &notesize);
    1282           0 :                 if (error)
    1283           0 :                         return (error);
    1284           0 :                 size += notesize;
    1285           0 :         }
    1286             : 
    1287           0 :         *sizep = size;
    1288           0 :         return (0);
    1289           0 : }
    1290             : 
    1291             : int
    1292           0 : coredump_note_elf(struct proc *p, void *iocookie, size_t *sizep)
    1293             : {
    1294           0 :         Elf_Note nhdr;
    1295             :         int size, notesize, error;
    1296             :         int namesize;
    1297           0 :         char name[64+ELFROUNDSIZE];
    1298           0 :         struct reg intreg;
    1299             : #ifdef PT_GETFPREGS
    1300           0 :         struct fpreg freg;
    1301             : #endif
    1302             : 
    1303             :         size = 0;
    1304             : 
    1305           0 :         snprintf(name, sizeof(name)-ELFROUNDSIZE, "%s@%d",
    1306           0 :             "OpenBSD", p->p_tid + THREAD_PID_OFFSET);
    1307           0 :         namesize = strlen(name) + 1;
    1308           0 :         memset(name + namesize, 0, elfround(namesize) - namesize);
    1309             : 
    1310           0 :         notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg));
    1311           0 :         if (iocookie) {
    1312           0 :                 error = process_read_regs(p, &intreg);
    1313           0 :                 if (error)
    1314           0 :                         return (error);
    1315             : 
    1316           0 :                 nhdr.namesz = namesize;
    1317           0 :                 nhdr.descsz = sizeof(intreg);
    1318           0 :                 nhdr.type = NT_OPENBSD_REGS;
    1319             : 
    1320           0 :                 error = coredump_writenote_elf(p, iocookie, &nhdr,
    1321             :                     name, &intreg);
    1322           0 :                 if (error)
    1323           0 :                         return (error);
    1324             : 
    1325             :         }
    1326             :         size += notesize;
    1327             : 
    1328             : #ifdef PT_GETFPREGS
    1329           0 :         notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg));
    1330           0 :         if (iocookie) {
    1331           0 :                 error = process_read_fpregs(p, &freg);
    1332           0 :                 if (error)
    1333           0 :                         return (error);
    1334             : 
    1335           0 :                 nhdr.namesz = namesize;
    1336           0 :                 nhdr.descsz = sizeof(freg);
    1337           0 :                 nhdr.type = NT_OPENBSD_FPREGS;
    1338             : 
    1339           0 :                 error = coredump_writenote_elf(p, iocookie, &nhdr, name, &freg);
    1340           0 :                 if (error)
    1341           0 :                         return (error);
    1342             :         }
    1343           0 :         size += notesize;
    1344             : #endif
    1345             : 
    1346           0 :         *sizep = size;
    1347             :         /* XXX Add hook for machdep per-LWP notes. */
    1348           0 :         return (0);
    1349           0 : }
    1350             : 
    1351             : int
    1352           0 : coredump_writenote_elf(struct proc *p, void *cookie, Elf_Note *nhdr,
    1353             :     const char *name, void *data)
    1354             : {
    1355             :         int error;
    1356             : 
    1357           0 :         error = coredump_write(cookie, UIO_SYSSPACE, nhdr, sizeof(*nhdr));
    1358           0 :         if (error)
    1359           0 :                 return error;
    1360             : 
    1361           0 :         error = coredump_write(cookie, UIO_SYSSPACE, name,
    1362           0 :             elfround(nhdr->namesz));
    1363           0 :         if (error)
    1364           0 :                 return error;
    1365             : 
    1366           0 :         return coredump_write(cookie, UIO_SYSSPACE, data, nhdr->descsz);
    1367           0 : }
    1368             : #endif /* !SMALL_KERNEL */

Generated by: LCOV version 1.13