1*131b88b7Sjca /* $OpenBSD: kern_exec.c,v 1.183 2016/09/03 14:28:24 jca Exp $ */ 25ac46f4aSniklas /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /*- 5df930be7Sderaadt * Copyright (C) 1993, 1994 Christopher G. Demetriou 6df930be7Sderaadt * Copyright (C) 1992 Wolfgang Solfrank. 7df930be7Sderaadt * Copyright (C) 1992 TooLs GmbH. 8df930be7Sderaadt * All rights reserved. 9df930be7Sderaadt * 10df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 11df930be7Sderaadt * modification, are permitted provided that the following conditions 12df930be7Sderaadt * are met: 13df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 14df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 15df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 16df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 17df930be7Sderaadt * documentation and/or other materials provided with the distribution. 18df930be7Sderaadt * 3. All advertising materials mentioning features or use of this software 19df930be7Sderaadt * must display the following acknowledgement: 20df930be7Sderaadt * This product includes software developed by TooLs GmbH. 21df930be7Sderaadt * 4. The name of TooLs GmbH may not be used to endorse or promote products 22df930be7Sderaadt * derived from this software without specific prior written permission. 23df930be7Sderaadt * 24df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 25df930be7Sderaadt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26df930be7Sderaadt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27df930be7Sderaadt * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28df930be7Sderaadt * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29df930be7Sderaadt * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30df930be7Sderaadt * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31df930be7Sderaadt * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32df930be7Sderaadt * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33df930be7Sderaadt * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34df930be7Sderaadt */ 35df930be7Sderaadt 36df930be7Sderaadt #include <sys/param.h> 37df930be7Sderaadt #include <sys/systm.h> 38df930be7Sderaadt #include <sys/filedesc.h> 39df930be7Sderaadt #include <sys/kernel.h> 40df930be7Sderaadt #include <sys/proc.h> 41df930be7Sderaadt #include <sys/mount.h> 42df930be7Sderaadt #include <sys/malloc.h> 43dbe27ba0Stedu #include <sys/pool.h> 44df930be7Sderaadt #include <sys/namei.h> 45df930be7Sderaadt #include <sys/vnode.h> 46df930be7Sderaadt #include <sys/file.h> 47df930be7Sderaadt #include <sys/acct.h> 48df930be7Sderaadt #include <sys/exec.h> 49df930be7Sderaadt #include <sys/ktrace.h> 50df930be7Sderaadt #include <sys/resourcevar.h> 51df930be7Sderaadt #include <sys/wait.h> 52df930be7Sderaadt #include <sys/mman.h> 53df930be7Sderaadt #include <sys/signalvar.h> 54df930be7Sderaadt #include <sys/stat.h> 55faa48718Sart #include <sys/conf.h> 56df174574Sderaadt #include <sys/pledge.h> 575ac46f4aSniklas #ifdef SYSVSHM 585ac46f4aSniklas #include <sys/shm.h> 595ac46f4aSniklas #endif 60df930be7Sderaadt 61df930be7Sderaadt #include <sys/syscallargs.h> 62df930be7Sderaadt 63fde894e5Stedu #include <uvm/uvm_extern.h> 64fde894e5Stedu 65c6319251Sguenther #ifdef __HAVE_MD_TCB 66c6319251Sguenther # include <machine/tcb.h> 67c6319251Sguenther #endif 68c6319251Sguenther 69b324ced2Skettenis const struct kmem_va_mode kv_exec = { 70b324ced2Skettenis .kv_wait = 1, 71b324ced2Skettenis .kv_map = &exec_map 72b324ced2Skettenis }; 73b324ced2Skettenis 74586305f1Sart /* 754a5480feSart * Map the shared signal code. 764a5480feSart */ 77924be113Sguenther int exec_sigcode_map(struct process *, struct emul *); 784a5480feSart 794a5480feSart /* 80b8736dc1Sderaadt * If non-zero, stackgap_random specifies the upper limit of the random gap size 812bda40dcSmiod * added to the fixed stack position. Must be n^2. 82586305f1Sart */ 83312d058fSderaadt int stackgap_random = STACKGAP_RANDOM; 84586305f1Sart 85df930be7Sderaadt /* 86df930be7Sderaadt * check exec: 87df930be7Sderaadt * given an "executable" described in the exec package's namei info, 88df930be7Sderaadt * see what we can do with it. 89df930be7Sderaadt * 90df930be7Sderaadt * ON ENTRY: 91df930be7Sderaadt * exec package with appropriate namei info 92df930be7Sderaadt * proc pointer of exec'ing proc 93df930be7Sderaadt * NO SELF-LOCKED VNODES 94df930be7Sderaadt * 95df930be7Sderaadt * ON EXIT: 96df930be7Sderaadt * error: nothing held, etc. exec header still allocated. 97df930be7Sderaadt * ok: filled exec package, one locked vnode. 98df930be7Sderaadt * 99df930be7Sderaadt * EXEC SWITCH ENTRY: 100df930be7Sderaadt * Locked vnode to check, exec package, proc. 101df930be7Sderaadt * 102df930be7Sderaadt * EXEC SWITCH EXIT: 103df930be7Sderaadt * ok: return 0, filled exec package, one locked vnode. 104df930be7Sderaadt * error: destructive: 105a3c911baSschwarze * everything deallocated except exec header. 106d84b7fccSmiod * non-destructive: 107df930be7Sderaadt * error code, locked vnode, exec header unmodified 108df930be7Sderaadt */ 109df930be7Sderaadt int 110158fb4f9Sjsg check_exec(struct proc *p, struct exec_package *epp) 111df930be7Sderaadt { 112df930be7Sderaadt int error, i; 113df930be7Sderaadt struct vnode *vp; 114df930be7Sderaadt struct nameidata *ndp; 1159b355cb2Smillert size_t resid; 116df930be7Sderaadt 117df930be7Sderaadt ndp = epp->ep_ndp; 118df930be7Sderaadt ndp->ni_cnd.cn_nameiop = LOOKUP; 119df930be7Sderaadt ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME; 120df930be7Sderaadt /* first get the vnode */ 1215ac46f4aSniklas if ((error = namei(ndp)) != 0) 122bcfbf755Sniklas return (error); 123df930be7Sderaadt epp->ep_vp = vp = ndp->ni_vp; 124df930be7Sderaadt 125df930be7Sderaadt /* check for regular file */ 12668bf7897Stholo if (vp->v_type == VDIR) { 12768bf7897Stholo error = EISDIR; 12868bf7897Stholo goto bad1; 12968bf7897Stholo } 130df930be7Sderaadt if (vp->v_type != VREG) { 131df930be7Sderaadt error = EACCES; 132df930be7Sderaadt goto bad1; 133df930be7Sderaadt } 134df930be7Sderaadt 135df930be7Sderaadt /* get attributes */ 1365ac46f4aSniklas if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0) 137df930be7Sderaadt goto bad1; 138df930be7Sderaadt 139df930be7Sderaadt /* Check mount point */ 140df930be7Sderaadt if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 141df930be7Sderaadt error = EACCES; 142df930be7Sderaadt goto bad1; 143df930be7Sderaadt } 144e55d0f86Sart 14551f754c1Sart if ((vp->v_mount->mnt_flag & MNT_NOSUID)) 14651f754c1Sart epp->ep_vap->va_mode &= ~(VSUID | VSGID); 147bfa108a0Sderaadt 148df930be7Sderaadt /* check access. for root we have to see if any exec bit on */ 1495ac46f4aSniklas if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0) 150df930be7Sderaadt goto bad1; 151df930be7Sderaadt if ((epp->ep_vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) { 152df930be7Sderaadt error = EACCES; 153df930be7Sderaadt goto bad1; 154df930be7Sderaadt } 155df930be7Sderaadt 156df930be7Sderaadt /* try to open it */ 1575ac46f4aSniklas if ((error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) != 0) 158df930be7Sderaadt goto bad1; 159df930be7Sderaadt 160d84dbf2eSart /* unlock vp, we need it unlocked from here */ 161937fcae7Snatano VOP_UNLOCK(vp, p); 162d84dbf2eSart 163df930be7Sderaadt /* now we have the file, get the exec header */ 1645ac46f4aSniklas error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0, 165d84dbf2eSart UIO_SYSSPACE, 0, p->p_ucred, &resid, p); 1665ac46f4aSniklas if (error) 167df930be7Sderaadt goto bad2; 168df930be7Sderaadt epp->ep_hdrvalid = epp->ep_hdrlen - resid; 169df930be7Sderaadt 170df930be7Sderaadt /* 171df930be7Sderaadt * set up the vmcmds for creation of the process 172df930be7Sderaadt * address space 173df930be7Sderaadt */ 174df930be7Sderaadt error = ENOEXEC; 175df930be7Sderaadt for (i = 0; i < nexecs && error != 0; i++) { 176df930be7Sderaadt int newerror; 177df930be7Sderaadt 178df930be7Sderaadt if (execsw[i].es_check == NULL) 179df930be7Sderaadt continue; 180df930be7Sderaadt newerror = (*execsw[i].es_check)(p, epp); 181e20a449dStedu if (!newerror && !(epp->ep_emul->e_flags & EMUL_ENABLED)) 182800da8d8Smiod newerror = EPERM; 183df930be7Sderaadt /* make sure the first "interesting" error code is saved. */ 184df930be7Sderaadt if (!newerror || error == ENOEXEC) 185df930be7Sderaadt error = newerror; 186df930be7Sderaadt if (epp->ep_flags & EXEC_DESTR && error != 0) 187bcfbf755Sniklas return (error); 188df930be7Sderaadt } 189df930be7Sderaadt if (!error) { 190df930be7Sderaadt /* check that entry point is sane */ 191ab30c277Spefo if (epp->ep_entry > VM_MAXUSER_ADDRESS) { 192df930be7Sderaadt error = ENOEXEC; 193ab30c277Spefo } 194df930be7Sderaadt 195df930be7Sderaadt /* check limits */ 196df930be7Sderaadt if ((epp->ep_tsize > MAXTSIZ) || 197df930be7Sderaadt (epp->ep_dsize > p->p_rlimit[RLIMIT_DATA].rlim_cur)) 198df930be7Sderaadt error = ENOMEM; 199df930be7Sderaadt 200df930be7Sderaadt if (!error) 201df930be7Sderaadt return (0); 202df930be7Sderaadt } 203df930be7Sderaadt 204df930be7Sderaadt /* 205df930be7Sderaadt * free any vmspace-creation commands, 206df930be7Sderaadt * and release their references 207df930be7Sderaadt */ 208df930be7Sderaadt kill_vmcmds(&epp->ep_vmcmds); 209df930be7Sderaadt 210df930be7Sderaadt bad2: 211df930be7Sderaadt /* 212d84dbf2eSart * close the vnode, free the pathname buf, and punt. 213df930be7Sderaadt */ 214df930be7Sderaadt vn_close(vp, FREAD, p->p_ucred, p); 215dbe27ba0Stedu pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf); 216bcfbf755Sniklas return (error); 217df930be7Sderaadt 218df930be7Sderaadt bad1: 219df930be7Sderaadt /* 220df930be7Sderaadt * free the namei pathname buffer, and put the vnode 221df930be7Sderaadt * (which we don't yet have open). 222df930be7Sderaadt */ 223dbe27ba0Stedu pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf); 224df930be7Sderaadt vput(vp); 225bcfbf755Sniklas return (error); 226df930be7Sderaadt } 227df930be7Sderaadt 228df930be7Sderaadt /* 229df930be7Sderaadt * exec system call 230df930be7Sderaadt */ 2315ac46f4aSniklas int 232158fb4f9Sjsg sys_execve(struct proc *p, void *v, register_t *retval) 233df930be7Sderaadt { 234586305f1Sart struct sys_execve_args /* { 23501b77f95Shenning syscallarg(const char *) path; 23601b77f95Shenning syscallarg(char *const *) argp; 23701b77f95Shenning syscallarg(char *const *) envp; 238df930be7Sderaadt } */ *uap = v; 239e20a449dStedu int error; 240df930be7Sderaadt struct exec_package pack; 241df930be7Sderaadt struct nameidata nid; 242df930be7Sderaadt struct vattr attr; 243df930be7Sderaadt struct ucred *cred = p->p_ucred; 244df930be7Sderaadt char *argp; 245d8434bb1Stholo char * const *cpp, *dp, *sp; 2465e0c3889Sguenther #ifdef KTRACE 2475e0c3889Sguenther char *env_start; 2485e0c3889Sguenther #endif 249bfb8af8fSguenther struct process *pr = p->p_p; 250df930be7Sderaadt long argc, envc; 251586305f1Sart size_t len, sgap; 252cc576edfSmickey #ifdef MACHINE_STACK_GROWS_UP 253cc576edfSmickey size_t slen; 254cc576edfSmickey #endif 255df930be7Sderaadt char *stack; 256df930be7Sderaadt struct ps_strings arginfo; 257924be113Sguenther struct vmspace *vm = pr->ps_vmspace; 258df930be7Sderaadt char **tmpfap; 259eb5fafa1Sderaadt extern struct emul emul_native; 2607359b57aStedu struct vnode *otvp; 261df930be7Sderaadt 2622ea51a70Sguenther /* get other threads to stop */ 2632ea51a70Sguenther if ((error = single_thread_set(p, SINGLE_UNWIND, 1))) 2641192233bSguenther return (error); 2652ea51a70Sguenther 266df930be7Sderaadt /* 267d5f75ac0Sart * Cheap solution to complicated problems. 268d5f75ac0Sart * Mark this process as "leave me alone, I'm execing". 269d5f75ac0Sart */ 2706b6f3ef9Sguenther atomic_setbits_int(&pr->ps_flags, PS_INEXEC); 271d5f75ac0Sart 27245573b1fSkettenis NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 273345a92b4Ssemarie nid.ni_pledge = PLEDGE_EXEC; 274df930be7Sderaadt 275df930be7Sderaadt /* 276df930be7Sderaadt * initialize the fields of the exec package. 277df930be7Sderaadt */ 278d8434bb1Stholo pack.ep_name = (char *)SCARG(uap, path); 279176819c2Sart pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK); 280df930be7Sderaadt pack.ep_hdrlen = exec_maxhdrsz; 281df930be7Sderaadt pack.ep_hdrvalid = 0; 282df930be7Sderaadt pack.ep_ndp = &nid; 283c0c22b04Stedu pack.ep_interp = NULL; 284df930be7Sderaadt pack.ep_emul_arg = NULL; 2851bdf816eSart VMCMDSET_INIT(&pack.ep_vmcmds); 286df930be7Sderaadt pack.ep_vap = &attr; 287eb5fafa1Sderaadt pack.ep_emul = &emul_native; 288df930be7Sderaadt pack.ep_flags = 0; 289df930be7Sderaadt 290df930be7Sderaadt /* see if we can run it. */ 291ab30c277Spefo if ((error = check_exec(p, &pack)) != 0) { 292df930be7Sderaadt goto freehdr; 293ab30c277Spefo } 294df930be7Sderaadt 295df930be7Sderaadt /* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */ 296df930be7Sderaadt 297df930be7Sderaadt /* allocate an argument buffer */ 298b324ced2Skettenis argp = km_alloc(NCARGS, &kv_exec, &kp_pageable, &kd_waitok); 299df930be7Sderaadt #ifdef DIAGNOSTIC 300b5099d50Snordin if (argp == NULL) 301df930be7Sderaadt panic("execve: argp == NULL"); 302df930be7Sderaadt #endif 303df930be7Sderaadt dp = argp; 304df930be7Sderaadt argc = 0; 305df930be7Sderaadt 306df930be7Sderaadt /* copy the fake args list, if there's one, freeing it as we go */ 307df930be7Sderaadt if (pack.ep_flags & EXEC_HASARGL) { 308df930be7Sderaadt tmpfap = pack.ep_fa; 309df930be7Sderaadt while (*tmpfap != NULL) { 310df930be7Sderaadt char *cp; 311df930be7Sderaadt 312df930be7Sderaadt cp = *tmpfap; 313df930be7Sderaadt while (*cp) 314df930be7Sderaadt *dp++ = *cp++; 315227892b1Sthib *dp++ = '\0'; 316df930be7Sderaadt 3179e8577e7Stedu free(*tmpfap, M_EXEC, 0); 318df930be7Sderaadt tmpfap++; argc++; 319df930be7Sderaadt } 3209e8577e7Stedu free(pack.ep_fa, M_EXEC, 0); 321df930be7Sderaadt pack.ep_flags &= ~EXEC_HASARGL; 322df930be7Sderaadt } 323df930be7Sderaadt 324df930be7Sderaadt /* Now get argv & environment */ 325df930be7Sderaadt if (!(cpp = SCARG(uap, argp))) { 326a5ceb13eSmickey error = EFAULT; 327df930be7Sderaadt goto bad; 328df930be7Sderaadt } 329df930be7Sderaadt 330df930be7Sderaadt if (pack.ep_flags & EXEC_SKIPARG) 331df930be7Sderaadt cpp++; 332df930be7Sderaadt 333df930be7Sderaadt while (1) { 334df930be7Sderaadt len = argp + ARG_MAX - dp; 3355ac46f4aSniklas if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) 336df930be7Sderaadt goto bad; 337df930be7Sderaadt if (!sp) 338df930be7Sderaadt break; 3395ac46f4aSniklas if ((error = copyinstr(sp, dp, len, &len)) != 0) { 340df930be7Sderaadt if (error == ENAMETOOLONG) 341df930be7Sderaadt error = E2BIG; 342df930be7Sderaadt goto bad; 343df930be7Sderaadt } 344df930be7Sderaadt dp += len; 345df930be7Sderaadt cpp++; 346df930be7Sderaadt argc++; 347df930be7Sderaadt } 348df930be7Sderaadt 34974212563Stedu /* must have at least one argument */ 35074212563Stedu if (argc == 0) { 35174212563Stedu error = EINVAL; 35274212563Stedu goto bad; 35374212563Stedu } 35474212563Stedu 3555e0c3889Sguenther #ifdef KTRACE 3565e0c3889Sguenther if (KTRPOINT(p, KTR_EXECARGS)) 3575e0c3889Sguenther ktrexec(p, KTR_EXECARGS, argp, dp - argp); 3585e0c3889Sguenther #endif 3595e0c3889Sguenther 360df930be7Sderaadt envc = 0; 361507f831cSmickey /* environment does not need to be there */ 3625ac46f4aSniklas if ((cpp = SCARG(uap, envp)) != NULL ) { 3635e0c3889Sguenther #ifdef KTRACE 3645e0c3889Sguenther env_start = dp; 3655e0c3889Sguenther #endif 366df930be7Sderaadt while (1) { 367df930be7Sderaadt len = argp + ARG_MAX - dp; 3685ac46f4aSniklas if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) 369df930be7Sderaadt goto bad; 370df930be7Sderaadt if (!sp) 371df930be7Sderaadt break; 3725ac46f4aSniklas if ((error = copyinstr(sp, dp, len, &len)) != 0) { 373df930be7Sderaadt if (error == ENAMETOOLONG) 374df930be7Sderaadt error = E2BIG; 375df930be7Sderaadt goto bad; 376df930be7Sderaadt } 377df930be7Sderaadt dp += len; 378df930be7Sderaadt cpp++; 379df930be7Sderaadt envc++; 380df930be7Sderaadt } 3815e0c3889Sguenther 3825e0c3889Sguenther #ifdef KTRACE 3835e0c3889Sguenther if (KTRPOINT(p, KTR_EXECENV)) 3845e0c3889Sguenther ktrexec(p, KTR_EXECENV, env_start, dp - env_start); 3855e0c3889Sguenther #endif 386df930be7Sderaadt } 387df930be7Sderaadt 388b8736dc1Sderaadt dp = (char *)(((long)dp + _STACKALIGNBYTES) & ~_STACKALIGNBYTES); 389df930be7Sderaadt 390586305f1Sart sgap = STACKGAPLEN; 3912bda40dcSmiod 3922bda40dcSmiod /* 3932bda40dcSmiod * If we have enabled random stackgap, the stack itself has already 3942bda40dcSmiod * been moved from a random location, but is still aligned to a page 3952bda40dcSmiod * boundary. Provide the lower bits of random placement now. 3962bda40dcSmiod */ 397b8736dc1Sderaadt if (stackgap_random != 0) { 3982bda40dcSmiod sgap += arc4random() & PAGE_MASK; 399b8736dc1Sderaadt sgap = (sgap + _STACKALIGNBYTES) & ~_STACKALIGNBYTES; 400b8736dc1Sderaadt } 401b8736dc1Sderaadt 402df930be7Sderaadt /* Now check if args & environ fit into new stack */ 403df930be7Sderaadt len = ((argc + envc + 2 + pack.ep_emul->e_arglen) * sizeof(char *) + 4044a5480feSart sizeof(long) + dp + sgap + sizeof(struct ps_strings)) - argp; 405df930be7Sderaadt 406b8736dc1Sderaadt len = (len + _STACKALIGNBYTES) &~ _STACKALIGNBYTES; 407df930be7Sderaadt 408df930be7Sderaadt if (len > pack.ep_ssize) { /* in effect, compare to initial limit */ 409df930be7Sderaadt error = ENOMEM; 410df930be7Sderaadt goto bad; 411df930be7Sderaadt } 412df930be7Sderaadt 413df930be7Sderaadt /* adjust "active stack depth" for process VSZ */ 414df930be7Sderaadt pack.ep_ssize = len; /* maybe should go elsewhere, but... */ 415df930be7Sderaadt 41686607369Sart /* 4172ea51a70Sguenther * we're committed: any further errors will kill the process, so 4182ea51a70Sguenther * kill the other threads now. 4192ea51a70Sguenther */ 4202ea51a70Sguenther single_thread_set(p, SINGLE_EXIT, 0); 4212ea51a70Sguenther 4222ea51a70Sguenther /* 42386607369Sart * Prepare vmspace for remapping. Note that uvmspace_exec can replace 424924be113Sguenther * pr_vmspace! 42586607369Sart */ 426cac1bff1Sart uvmspace_exec(p, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); 427df930be7Sderaadt 428924be113Sguenther vm = pr->ps_vmspace; 429df930be7Sderaadt /* Now map address space */ 430ff3fdef1Skettenis vm->vm_taddr = (char *)trunc_page(pack.ep_taddr); 431ff3fdef1Skettenis vm->vm_tsize = atop(round_page(pack.ep_taddr + pack.ep_tsize) - 432ff3fdef1Skettenis trunc_page(pack.ep_taddr)); 433ff3fdef1Skettenis vm->vm_daddr = (char *)trunc_page(pack.ep_daddr); 434ff3fdef1Skettenis vm->vm_dsize = atop(round_page(pack.ep_daddr + pack.ep_dsize) - 435ff3fdef1Skettenis trunc_page(pack.ep_daddr)); 4360ebeee85Sderaadt vm->vm_dused = 0; 43776d52da2Smartin vm->vm_ssize = atop(round_page(pack.ep_ssize)); 438df930be7Sderaadt vm->vm_maxsaddr = (char *)pack.ep_maxsaddr; 439d9040bf8Smickey vm->vm_minsaddr = (char *)pack.ep_minsaddr; 440df930be7Sderaadt 441df930be7Sderaadt /* create the new process's VM space by running the vmcmds */ 442df930be7Sderaadt #ifdef DIAGNOSTIC 443df930be7Sderaadt if (pack.ep_vmcmds.evs_used == 0) 444df930be7Sderaadt panic("execve: no vmcmds"); 445df930be7Sderaadt #endif 4461e04e351Sart error = exec_process_vmcmds(p, &pack); 447df930be7Sderaadt 448df930be7Sderaadt /* if an error happened, deallocate and punt */ 449df930be7Sderaadt if (error) 450df930be7Sderaadt goto exec_abort; 451df930be7Sderaadt 45256b6d613Skettenis /* old "stackgap" is gone now */ 45356b6d613Skettenis pr->ps_stackgap = 0; 45456b6d613Skettenis 45556b6d613Skettenis #ifdef MACHINE_STACK_GROWS_UP 4567180d9eaSmiod pr->ps_strings = (vaddr_t)vm->vm_maxsaddr + sgap; 45756b6d613Skettenis if (uvm_map_protect(&vm->vm_map, (vaddr_t)vm->vm_maxsaddr, 45856b6d613Skettenis trunc_page(pr->ps_strings), PROT_NONE, TRUE)) 45956b6d613Skettenis goto exec_abort; 46056b6d613Skettenis #else 4617180d9eaSmiod pr->ps_strings = (vaddr_t)vm->vm_minsaddr - sizeof(arginfo) - sgap; 46256b6d613Skettenis if (uvm_map_protect(&vm->vm_map, 46356b6d613Skettenis round_page(pr->ps_strings + sizeof(arginfo)), 46456b6d613Skettenis (vaddr_t)vm->vm_minsaddr, PROT_NONE, TRUE)) 46556b6d613Skettenis goto exec_abort; 46656b6d613Skettenis #endif 46756b6d613Skettenis 468df930be7Sderaadt /* remember information about the process */ 469df930be7Sderaadt arginfo.ps_nargvstr = argc; 470df930be7Sderaadt arginfo.ps_nenvstr = envc; 471df930be7Sderaadt 472910e6419Smickey #ifdef MACHINE_STACK_GROWS_UP 4737180d9eaSmiod stack = (char *)vm->vm_maxsaddr + sizeof(arginfo) + sgap; 474f18df0c5Skettenis slen = len - sizeof(arginfo) - sgap; 475910e6419Smickey #else 4767180d9eaSmiod stack = (char *)(vm->vm_minsaddr - len); 477910e6419Smickey #endif 478df930be7Sderaadt /* Now copy argc, args & environ to new stack */ 479df930be7Sderaadt if (!(*pack.ep_emul->e_copyargs)(&pack, &arginfo, stack, argp)) 480df930be7Sderaadt goto exec_abort; 481df930be7Sderaadt 482df930be7Sderaadt /* copy out the process's ps_strings structure */ 483a78264c4Skettenis if (copyout(&arginfo, (char *)pr->ps_strings, sizeof(arginfo))) 484df930be7Sderaadt goto exec_abort; 485df930be7Sderaadt 48618914fdfSguenther stopprofclock(pr); /* stop profiling */ 487df930be7Sderaadt fdcloseexec(p); /* handle close on exec */ 488611924b3Smiod execsigs(p); /* reset caught signals */ 489c6319251Sguenther TCB_SET(p, NULL); /* reset the TCB address */ 490440e6fe6Sguenther pr->ps_kbind_addr = 0; /* reset the kbind bits */ 491440e6fe6Sguenther pr->ps_kbind_cookie = 0; 4927730d1d9Sderaadt arc4random_buf(&pr->ps_sigcookie, sizeof pr->ps_sigcookie); 493df930be7Sderaadt 494df930be7Sderaadt /* set command name & other accounting info */ 49591ba896dStedu memset(p->p_comm, 0, sizeof(p->p_comm)); 496df930be7Sderaadt len = min(nid.ni_cnd.cn_namelen, MAXCOMLEN); 4972955d5bcStedu memcpy(p->p_comm, nid.ni_cnd.cn_nameptr, len); 4980839b846Smikeb pr->ps_acflag &= ~AFORK; 499df930be7Sderaadt 500cf6677a6Sguenther /* record proc's vnode, for use by sysctl */ 5014ab8ed70Sguenther otvp = pr->ps_textvp; 502627b2c48Sthib vref(pack.ep_vp); 5034ab8ed70Sguenther pr->ps_textvp = pack.ep_vp; 5047359b57aStedu if (otvp) 5057359b57aStedu vrele(otvp); 506df930be7Sderaadt 507e2590abeSguenther atomic_setbits_int(&pr->ps_flags, PS_EXEC); 508c0ce47d9Sguenther if (pr->ps_flags & PS_PPWAIT) { 509c0ce47d9Sguenther atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT); 510c0ce47d9Sguenther atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT); 511bfb8af8fSguenther wakeup(pr->ps_pptr); 512df930be7Sderaadt } 513df930be7Sderaadt 514df930be7Sderaadt /* 515855755d9Smillert * If process does execve() while it has a mismatched real, 516bfb8af8fSguenther * effective, or saved uid/gid, we set PS_SUGIDEXEC. 51725b40de6Sderaadt */ 518d559b8cbSguenther if (cred->cr_uid != cred->cr_ruid || 519d559b8cbSguenther cred->cr_uid != cred->cr_svuid || 520d559b8cbSguenther cred->cr_gid != cred->cr_rgid || 521d559b8cbSguenther cred->cr_gid != cred->cr_svgid) 522bfb8af8fSguenther atomic_setbits_int(&pr->ps_flags, PS_SUGIDEXEC); 523855755d9Smillert else 524bfb8af8fSguenther atomic_clearbits_int(&pr->ps_flags, PS_SUGIDEXEC); 52525b40de6Sderaadt 526df174574Sderaadt atomic_clearbits_int(&pr->ps_flags, PS_PLEDGE); 527df174574Sderaadt pledge_dropwpaths(pr); 528609289baSderaadt 52925b40de6Sderaadt /* 530df930be7Sderaadt * deal with set[ug]id. 53151f754c1Sart * MNT_NOEXEC has already been used to disable s[ug]id. 532df930be7Sderaadt */ 53351f754c1Sart if ((attr.va_mode & (VSUID | VSGID)) && proc_cansugid(p)) { 534bbf7a176Sderaadt int i; 535bbf7a176Sderaadt 536bfb8af8fSguenther atomic_setbits_int(&pr->ps_flags, PS_SUGID|PS_SUGIDEXEC); 53751f754c1Sart 538df930be7Sderaadt #ifdef KTRACE 539df930be7Sderaadt /* 540df930be7Sderaadt * If process is being ktraced, turn off - unless 541df930be7Sderaadt * root set it. 542df930be7Sderaadt */ 543a2e04e14Sguenther if (pr->ps_tracevp && !(pr->ps_traceflag & KTRFAC_ROOT)) 544a2e04e14Sguenther ktrcleartrace(pr); 545df930be7Sderaadt #endif 546d559b8cbSguenther p->p_ucred = cred = crcopy(cred); 547df930be7Sderaadt if (attr.va_mode & VSUID) 548d559b8cbSguenther cred->cr_uid = attr.va_uid; 549df930be7Sderaadt if (attr.va_mode & VSGID) 550d559b8cbSguenther cred->cr_gid = attr.va_gid; 551bbf7a176Sderaadt 552bbf7a176Sderaadt /* 553bba8c139Sderaadt * For set[ug]id processes, a few caveats apply to 554bba8c139Sderaadt * stdin, stdout, and stderr. 555bbf7a176Sderaadt */ 556638f0017Sguenther error = 0; 557638f0017Sguenther fdplock(p->p_fd); 558bbf7a176Sderaadt for (i = 0; i < 3; i++) { 559c3315ca6Sderaadt struct file *fp = NULL; 560c3315ca6Sderaadt 561af97e5cfSart /* 562af97e5cfSart * NOTE - This will never return NULL because of 5632addf348Sjmc * immature fds. The file descriptor table is not 564af97e5cfSart * shared because we're suid. 565af97e5cfSart */ 566af97e5cfSart fp = fd_getfile(p->p_fd, i); 567c3315ca6Sderaadt 568c3315ca6Sderaadt /* 569c3315ca6Sderaadt * Ensure that stdin, stdout, and stderr are already 570c3315ca6Sderaadt * allocated. We do not want userland to accidentally 571c3315ca6Sderaadt * allocate descriptors in this range which has implied 572c3315ca6Sderaadt * meaning to libc. 573c3315ca6Sderaadt */ 574c3315ca6Sderaadt if (fp == NULL) { 575c3315ca6Sderaadt short flags = FREAD | (i == 0 ? 0 : FWRITE); 576faa48718Sart struct vnode *vp; 577bbf7a176Sderaadt int indx; 57858d9451eSart 579bbf7a176Sderaadt if ((error = falloc(p, &fp, &indx)) != 0) 580638f0017Sguenther break; 581faa48718Sart #ifdef DIAGNOSTIC 582faa48718Sart if (indx != i) 583faa48718Sart panic("sys_execve: falloc indx != i"); 584faa48718Sart #endif 585faa48718Sart if ((error = cdevvp(getnulldev(), &vp)) != 0) { 586bb720fc6Sprovos fdremove(p->p_fd, indx); 58743c6a78bSart closef(fp, p); 588638f0017Sguenther break; 589bbf7a176Sderaadt } 590d559b8cbSguenther if ((error = VOP_OPEN(vp, flags, cred, p)) != 0) { 591faa48718Sart fdremove(p->p_fd, indx); 59243c6a78bSart closef(fp, p); 593faa48718Sart vrele(vp); 594638f0017Sguenther break; 595faa48718Sart } 596faa48718Sart if (flags & FWRITE) 597faa48718Sart vp->v_writecount++; 59858d9451eSart fp->f_flag = flags; 599bbf7a176Sderaadt fp->f_type = DTYPE_VNODE; 600bbf7a176Sderaadt fp->f_ops = &vnops; 601faa48718Sart fp->f_data = (caddr_t)vp; 60206a89b59Sguenther FILE_SET_MATURE(fp, p); 603bbf7a176Sderaadt } 604bbf7a176Sderaadt } 605638f0017Sguenther fdpunlock(p->p_fd); 606638f0017Sguenther if (error) 607638f0017Sguenther goto exec_abort; 60825b40de6Sderaadt } else 609bfb8af8fSguenther atomic_clearbits_int(&pr->ps_flags, PS_SUGID); 610d559b8cbSguenther 611a9ddc286Sguenther /* 612a9ddc286Sguenther * Reset the saved ugids and update the process's copy of the 613a9ddc286Sguenther * creds if the creds have been changed 614a9ddc286Sguenther */ 615d559b8cbSguenther if (cred->cr_uid != cred->cr_svuid || 616d559b8cbSguenther cred->cr_gid != cred->cr_svgid) { 617d559b8cbSguenther /* make sure we have unshared ucreds */ 618d559b8cbSguenther p->p_ucred = cred = crcopy(cred); 619d559b8cbSguenther cred->cr_svuid = cred->cr_uid; 620d559b8cbSguenther cred->cr_svgid = cred->cr_gid; 621d559b8cbSguenther } 622df930be7Sderaadt 623a9ddc286Sguenther if (pr->ps_ucred != cred) { 624a9ddc286Sguenther struct ucred *ocred; 625a9ddc286Sguenther 626a9ddc286Sguenther ocred = pr->ps_ucred; 627a9ddc286Sguenther crhold(cred); 628a9ddc286Sguenther pr->ps_ucred = cred; 629a9ddc286Sguenther crfree(ocred); 630a9ddc286Sguenther } 631a9ddc286Sguenther 632bfb8af8fSguenther if (pr->ps_flags & PS_SUGIDEXEC) { 633baf3eb4dSderaadt int i, s = splclock(); 634baf3eb4dSderaadt 6358f15e6a4Sguenther timeout_del(&pr->ps_realit_to); 6368f15e6a4Sguenther for (i = 0; i < nitems(pr->ps_timer); i++) { 6378f15e6a4Sguenther timerclear(&pr->ps_timer[i].it_interval); 6388f15e6a4Sguenther timerclear(&pr->ps_timer[i].it_value); 639baf3eb4dSderaadt } 64021b2622bSderaadt splx(s); 64121b2622bSderaadt } 64221b2622bSderaadt 6437b36c281Sguenther /* reset CPU time usage for the thread, but not the process */ 6447b36c281Sguenther timespecclear(&p->p_tu.tu_runtime); 6457b36c281Sguenther p->p_tu.tu_uticks = p->p_tu.tu_sticks = p->p_tu.tu_iticks = 0; 6467b36c281Sguenther 647b324ced2Skettenis km_free(argp, NCARGS, &kv_exec, &kp_pageable); 648df930be7Sderaadt 649dbe27ba0Stedu pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); 650d84dbf2eSart vn_close(pack.ep_vp, FREAD, cred, p); 651df930be7Sderaadt 6521a12e8a7Sprovos /* 6531a12e8a7Sprovos * notify others that we exec'd 6541a12e8a7Sprovos */ 655bfb8af8fSguenther KNOTE(&pr->ps_klist, NOTE_EXEC); 6561a12e8a7Sprovos 657df930be7Sderaadt /* setup new registers and do misc. setup. */ 658ab30c277Spefo if (pack.ep_emul->e_fixup != NULL) { 659ab30c277Spefo if ((*pack.ep_emul->e_fixup)(p, &pack) != 0) 660ab30c277Spefo goto free_pack_abort; 661ab30c277Spefo } 662910e6419Smickey #ifdef MACHINE_STACK_GROWS_UP 663cc576edfSmickey (*pack.ep_emul->e_setregs)(p, &pack, (u_long)stack + slen, retval); 664910e6419Smickey #else 665df930be7Sderaadt (*pack.ep_emul->e_setregs)(p, &pack, (u_long)stack, retval); 666910e6419Smickey #endif 667df930be7Sderaadt 6684a5480feSart /* map the process's signal trampoline code */ 669924be113Sguenther if (exec_sigcode_map(pr, pack.ep_emul)) 670c0c22b04Stedu goto free_pack_abort; 6714a5480feSart 6724c0d1b1bSmiod #ifdef __HAVE_EXEC_MD_MAP 6734c0d1b1bSmiod /* perform md specific mappings that process might need */ 6744c0d1b1bSmiod if (exec_md_map(p, &pack)) 6754c0d1b1bSmiod goto free_pack_abort; 6764c0d1b1bSmiod #endif 6774c0d1b1bSmiod 6786b6f3ef9Sguenther if (pr->ps_flags & PS_TRACED) 679df930be7Sderaadt psignal(p, SIGTRAP); 680df930be7Sderaadt 6817da957a5Sderaadt free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); 682df930be7Sderaadt 683abc163f4Stedu /* 684abc163f4Stedu * Call emulation specific exec hook. This can setup per-process 685abc163f4Stedu * p->p_emuldata or do any other per-process stuff an emulation needs. 686abc163f4Stedu * 687abc163f4Stedu * If we are executing process of different emulation than the 688abc163f4Stedu * original forked process, call e_proc_exit() of the old emulation 689abc163f4Stedu * first, then e_proc_exec() of new emulation. If the emulation is 690abc163f4Stedu * same, the exec hook code should deallocate any old emulation 691abc163f4Stedu * resources held previously by this process. 692abc163f4Stedu */ 6938f76f5adSguenther if (pr->ps_emul && pr->ps_emul->e_proc_exit && 6948f76f5adSguenther pr->ps_emul != pack.ep_emul) 6958f76f5adSguenther (*pr->ps_emul->e_proc_exit)(p); 696abc163f4Stedu 697d9f343eeSderaadt p->p_descfd = 255; 698d9f343eeSderaadt if ((pack.ep_flags & EXEC_HASFD) && pack.ep_fd < 255) 699d9f343eeSderaadt p->p_descfd = pack.ep_fd; 700d9f343eeSderaadt 701f68ce565Sderaadt if (pack.ep_flags & EXEC_WXNEEDED) 702f68ce565Sderaadt p->p_p->ps_flags |= PS_WXNEEDED; 703*131b88b7Sjca else 704*131b88b7Sjca p->p_p->ps_flags &= ~PS_WXNEEDED; 705f68ce565Sderaadt 706abc163f4Stedu /* 707abc163f4Stedu * Call exec hook. Emulation code may NOT store reference to anything 708abc163f4Stedu * from &pack. 709abc163f4Stedu */ 710abc163f4Stedu if (pack.ep_emul->e_proc_exec) 711abc163f4Stedu (*pack.ep_emul->e_proc_exec)(p, &pack); 712abc163f4Stedu 7135e0c3889Sguenther /* update ps_emul, the old value is no longer needed */ 7145e0c3889Sguenther pr->ps_emul = pack.ep_emul; 7155c025fc6Smarius 7166b6f3ef9Sguenther atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); 7174ec19540Skettenis single_thread_clear(p, P_SUSPSIG); 7185c025fc6Smarius 719bcfbf755Sniklas return (0); 720df930be7Sderaadt 721df930be7Sderaadt bad: 722df930be7Sderaadt /* free the vmspace-creation commands, and release their references */ 723df930be7Sderaadt kill_vmcmds(&pack.ep_vmcmds); 724df930be7Sderaadt /* kill any opened file descriptor, if necessary */ 725df930be7Sderaadt if (pack.ep_flags & EXEC_HASFD) { 726df930be7Sderaadt pack.ep_flags &= ~EXEC_HASFD; 727638f0017Sguenther fdplock(p->p_fd); 728df930be7Sderaadt (void) fdrelease(p, pack.ep_fd); 729638f0017Sguenther fdpunlock(p->p_fd); 730df930be7Sderaadt } 731c0c22b04Stedu if (pack.ep_interp != NULL) 732335c12deSmickey pool_put(&namei_pool, pack.ep_interp); 733c0c22b04Stedu if (pack.ep_emul_arg != NULL) 7347da957a5Sderaadt free(pack.ep_emul_arg, M_TEMP, pack.ep_emul_argsize); 735df930be7Sderaadt /* close and put the exec'd file */ 736d84dbf2eSart vn_close(pack.ep_vp, FREAD, cred, p); 737dbe27ba0Stedu pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); 738b324ced2Skettenis km_free(argp, NCARGS, &kv_exec, &kp_pageable); 739df930be7Sderaadt 740df930be7Sderaadt freehdr: 7417da957a5Sderaadt free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); 7426b6f3ef9Sguenther atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); 7434ec19540Skettenis single_thread_clear(p, P_SUSPSIG); 744a792ab75Sart 745bcfbf755Sniklas return (error); 746df930be7Sderaadt 747df930be7Sderaadt exec_abort: 748df930be7Sderaadt /* 749df930be7Sderaadt * the old process doesn't exist anymore. exit gracefully. 750df930be7Sderaadt * get rid of the (new) address space we have created, if any, get rid 751df930be7Sderaadt * of our namei data and vnode, and exit noting failure 752df930be7Sderaadt */ 75356e05e0fSart uvm_deallocate(&vm->vm_map, VM_MIN_ADDRESS, 75456e05e0fSart VM_MAXUSER_ADDRESS - VM_MIN_ADDRESS); 755c0c22b04Stedu if (pack.ep_interp != NULL) 756335c12deSmickey pool_put(&namei_pool, pack.ep_interp); 757c0c22b04Stedu if (pack.ep_emul_arg != NULL) 7587da957a5Sderaadt free(pack.ep_emul_arg, M_TEMP, pack.ep_emul_argsize); 759dbe27ba0Stedu pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); 760d84dbf2eSart vn_close(pack.ep_vp, FREAD, cred, p); 761b324ced2Skettenis km_free(argp, NCARGS, &kv_exec, &kp_pageable); 762ab30c277Spefo 763ab30c277Spefo free_pack_abort: 7647da957a5Sderaadt free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); 765802bb6acStedu exit1(p, W_EXITCODE(0, SIGABRT), EXIT_NORMAL); 766df930be7Sderaadt 767df930be7Sderaadt /* NOTREACHED */ 7686b6f3ef9Sguenther atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); 769a792ab75Sart 770bcfbf755Sniklas return (0); 771df930be7Sderaadt } 772df930be7Sderaadt 773df930be7Sderaadt 774df930be7Sderaadt void * 775158fb4f9Sjsg copyargs(struct exec_package *pack, struct ps_strings *arginfo, void *stack, 776158fb4f9Sjsg void *argp) 777df930be7Sderaadt { 778df930be7Sderaadt char **cpp = stack; 779df930be7Sderaadt char *dp, *sp; 780df930be7Sderaadt size_t len; 781df930be7Sderaadt void *nullp = NULL; 782d2b5d78fSart long argc = arginfo->ps_nargvstr; 783df930be7Sderaadt int envc = arginfo->ps_nenvstr; 784df930be7Sderaadt 785df930be7Sderaadt if (copyout(&argc, cpp++, sizeof(argc))) 786bcfbf755Sniklas return (NULL); 787df930be7Sderaadt 788df930be7Sderaadt dp = (char *) (cpp + argc + envc + 2 + pack->ep_emul->e_arglen); 789df930be7Sderaadt sp = argp; 790df930be7Sderaadt 791df930be7Sderaadt /* XXX don't copy them out, remap them! */ 792df930be7Sderaadt arginfo->ps_argvstr = cpp; /* remember location of argv for later */ 793df930be7Sderaadt 794df930be7Sderaadt for (; --argc >= 0; sp += len, dp += len) 795df930be7Sderaadt if (copyout(&dp, cpp++, sizeof(dp)) || 796df930be7Sderaadt copyoutstr(sp, dp, ARG_MAX, &len)) 797bcfbf755Sniklas return (NULL); 798df930be7Sderaadt 799df930be7Sderaadt if (copyout(&nullp, cpp++, sizeof(nullp))) 800bcfbf755Sniklas return (NULL); 801df930be7Sderaadt 802df930be7Sderaadt arginfo->ps_envstr = cpp; /* remember location of envp for later */ 803df930be7Sderaadt 804df930be7Sderaadt for (; --envc >= 0; sp += len, dp += len) 805df930be7Sderaadt if (copyout(&dp, cpp++, sizeof(dp)) || 806df930be7Sderaadt copyoutstr(sp, dp, ARG_MAX, &len)) 807bcfbf755Sniklas return (NULL); 808df930be7Sderaadt 809df930be7Sderaadt if (copyout(&nullp, cpp++, sizeof(nullp))) 810bcfbf755Sniklas return (NULL); 811df930be7Sderaadt 812bcfbf755Sniklas return (cpp); 813df930be7Sderaadt } 8144a5480feSart 8154a5480feSart int 816924be113Sguenther exec_sigcode_map(struct process *pr, struct emul *e) 8174a5480feSart { 8184a5480feSart vsize_t sz; 8194a5480feSart 8204a5480feSart sz = (vaddr_t)e->e_esigcode - (vaddr_t)e->e_sigcode; 8214a5480feSart 8224a5480feSart /* 8234a5480feSart * If we don't have a sigobject for this emulation, create one. 8244a5480feSart * 8254a5480feSart * sigobject is an anonymous memory object (just like SYSV shared 8264a5480feSart * memory) that we keep a permanent reference to and that we map 8274a5480feSart * in all processes that need this sigcode. The creation is simple, 8284a5480feSart * we create an object, add a permanent reference to it, map it in 8294a5480feSart * kernel space, copy out the sigcode to it and unmap it. 8307fb77204Sgrange * Then we map it with PROT_READ|PROT_EXEC into the process just 8314a5480feSart * the way sys_mmap would map it. 8324a5480feSart */ 8334a5480feSart if (e->e_sigobject == NULL) { 834b983598cSderaadt extern int sigfillsiz; 835b983598cSderaadt extern u_char sigfill[]; 836b983598cSderaadt size_t off; 8374a5480feSart vaddr_t va; 8384a5480feSart int r; 8394a5480feSart 8404a5480feSart e->e_sigobject = uao_create(sz, 0); 8414a5480feSart uao_reference(e->e_sigobject); /* permanent reference */ 8424a5480feSart 8434a5480feSart if ((r = uvm_map(kernel_map, &va, round_page(sz), e->e_sigobject, 8441e8cdc2eSderaadt 0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, 84515cd8707Sguenther MAP_INHERIT_SHARE, MADV_RANDOM, 0)))) { 846e481f8e1Smillert uao_detach(e->e_sigobject); 8474a5480feSart return (ENOMEM); 8484a5480feSart } 849b983598cSderaadt 850b983598cSderaadt for (off = 0; off < round_page(sz); off += sigfillsiz) 851b983598cSderaadt memcpy((caddr_t)va + off, sigfill, sigfillsiz); 852b983598cSderaadt memcpy((caddr_t)va, e->e_sigcode, sz); 8534a5480feSart uvm_unmap(kernel_map, va, va + round_page(sz)); 8544a5480feSart } 8554a5480feSart 856924be113Sguenther pr->ps_sigcode = 0; /* no hint */ 8574a5480feSart uao_reference(e->e_sigobject); 858924be113Sguenther if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_sigcode, round_page(sz), 8591e8cdc2eSderaadt e->e_sigobject, 0, 0, UVM_MAPFLAG(PROT_READ | PROT_EXEC, 86012ccc845Skettenis PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_COPY, 861a47732feSkettenis MADV_RANDOM, UVM_FLAG_COPYONW))) { 862e481f8e1Smillert uao_detach(e->e_sigobject); 8634a5480feSart return (ENOMEM); 8644a5480feSart } 8654a5480feSart 8667730d1d9Sderaadt /* Calculate PC at point of sigreturn entry */ 8677730d1d9Sderaadt pr->ps_sigcoderet = pr->ps_sigcode + 8687730d1d9Sderaadt (pr->ps_emul->e_esigret - pr->ps_emul->e_sigcode); 8697730d1d9Sderaadt 8704a5480feSart return (0); 8714a5480feSart } 872