1*d479e871Sclaudio /* $OpenBSD: kern_exec.c,v 1.260 2025/01/25 19:21:40 claudio 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/proc.h> 40a2c764f6Sderaadt #include <sys/user.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> 464b1f64dcSguenther #include <sys/fcntl.h> 47df930be7Sderaadt #include <sys/file.h> 48df930be7Sderaadt #include <sys/acct.h> 49df930be7Sderaadt #include <sys/exec.h> 50682e3c94Sguenther #include <sys/exec_elf.h> 51df930be7Sderaadt #include <sys/ktrace.h> 52df930be7Sderaadt #include <sys/resourcevar.h> 53df930be7Sderaadt #include <sys/mman.h> 54df930be7Sderaadt #include <sys/signalvar.h> 55df930be7Sderaadt #include <sys/stat.h> 56faa48718Sart #include <sys/conf.h> 57df174574Sderaadt #include <sys/pledge.h> 585ac46f4aSniklas #ifdef SYSVSHM 595ac46f4aSniklas #include <sys/shm.h> 605ac46f4aSniklas #endif 61df930be7Sderaadt 62df930be7Sderaadt #include <sys/syscallargs.h> 63df930be7Sderaadt 64fde894e5Stedu #include <uvm/uvm_extern.h> 65c6319251Sguenther #include <machine/tcb.h> 66c6319251Sguenther 67d82e6535Spirofti #include <sys/timetc.h> 68d82e6535Spirofti 695a72e03eSguenther struct uvm_object *sigobject; /* shared sigcode object */ 7013f0bae7Skettenis vaddr_t sigcode_va; 7113f0bae7Skettenis vsize_t sigcode_sz; 72d82e6535Spirofti struct uvm_object *timekeep_object; 73d82e6535Spirofti struct timekeep *timekeep; 74d82e6535Spirofti 758b23add8Sbeck void unveil_destroy(struct process *ps); 768b23add8Sbeck 77b324ced2Skettenis const struct kmem_va_mode kv_exec = { 78b324ced2Skettenis .kv_wait = 1, 79b324ced2Skettenis .kv_map = &exec_map 80b324ced2Skettenis }; 81b324ced2Skettenis 82586305f1Sart /* 834a5480feSart * Map the shared signal code. 844a5480feSart */ 855a72e03eSguenther int exec_sigcode_map(struct process *); 864a5480feSart 874a5480feSart /* 88d82e6535Spirofti * Map the shared timekeep page. 89d82e6535Spirofti */ 90d82e6535Spirofti int exec_timekeep_map(struct process *); 91d82e6535Spirofti 92d82e6535Spirofti /* 93b8736dc1Sderaadt * If non-zero, stackgap_random specifies the upper limit of the random gap size 942bda40dcSmiod * added to the fixed stack position. Must be n^2. 95586305f1Sart */ 96312d058fSderaadt int stackgap_random = STACKGAP_RANDOM; 97586305f1Sart 98df930be7Sderaadt /* 99df930be7Sderaadt * check exec: 100df930be7Sderaadt * given an "executable" described in the exec package's namei info, 101df930be7Sderaadt * see what we can do with it. 102df930be7Sderaadt * 103df930be7Sderaadt * ON ENTRY: 104df930be7Sderaadt * exec package with appropriate namei info 105df930be7Sderaadt * proc pointer of exec'ing proc 106df930be7Sderaadt * NO SELF-LOCKED VNODES 107df930be7Sderaadt * 108df930be7Sderaadt * ON EXIT: 109df930be7Sderaadt * error: nothing held, etc. exec header still allocated. 110df930be7Sderaadt * ok: filled exec package, one locked vnode. 111df930be7Sderaadt * 112df930be7Sderaadt * EXEC SWITCH ENTRY: 113df930be7Sderaadt * Locked vnode to check, exec package, proc. 114df930be7Sderaadt * 115df930be7Sderaadt * EXEC SWITCH EXIT: 116df930be7Sderaadt * ok: return 0, filled exec package, one locked vnode. 117df930be7Sderaadt * error: destructive: 118a3c911baSschwarze * everything deallocated except exec header. 119d84b7fccSmiod * non-destructive: 120df930be7Sderaadt * error code, locked vnode, exec header unmodified 121df930be7Sderaadt */ 122df930be7Sderaadt int 123158fb4f9Sjsg check_exec(struct proc *p, struct exec_package *epp) 124df930be7Sderaadt { 125df930be7Sderaadt int error, i; 126df930be7Sderaadt struct vnode *vp; 127df930be7Sderaadt struct nameidata *ndp; 1289b355cb2Smillert size_t resid; 129df930be7Sderaadt 130df930be7Sderaadt ndp = epp->ep_ndp; 131df930be7Sderaadt ndp->ni_cnd.cn_nameiop = LOOKUP; 132df930be7Sderaadt ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME; 13362111f95Sderaadt if (epp->ep_flags & EXEC_INDIR) 13462111f95Sderaadt ndp->ni_cnd.cn_flags |= BYPASSUNVEIL; 135df930be7Sderaadt /* first get the vnode */ 1365ac46f4aSniklas if ((error = namei(ndp)) != 0) 137bcfbf755Sniklas return (error); 138df930be7Sderaadt epp->ep_vp = vp = ndp->ni_vp; 139df930be7Sderaadt 140df930be7Sderaadt /* check for regular file */ 141df930be7Sderaadt if (vp->v_type != VREG) { 142df930be7Sderaadt error = EACCES; 143df930be7Sderaadt goto bad1; 144df930be7Sderaadt } 145df930be7Sderaadt 146df930be7Sderaadt /* get attributes */ 1475ac46f4aSniklas if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0) 148df930be7Sderaadt goto bad1; 149df930be7Sderaadt 150df930be7Sderaadt /* Check mount point */ 151df930be7Sderaadt if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 152df930be7Sderaadt error = EACCES; 153df930be7Sderaadt goto bad1; 154df930be7Sderaadt } 155e55d0f86Sart 1564ea7ed56Sderaadt /* SUID programs may not be started with execpromises */ 1574ea7ed56Sderaadt if ((epp->ep_vap->va_mode & (VSUID | VSGID)) && 1584ea7ed56Sderaadt (p->p_p->ps_flags & PS_EXECPLEDGE)) { 1594ea7ed56Sderaadt error = EACCES; 1604ea7ed56Sderaadt goto bad1; 1614ea7ed56Sderaadt } 1624ea7ed56Sderaadt 16351f754c1Sart if ((vp->v_mount->mnt_flag & MNT_NOSUID)) 16451f754c1Sart epp->ep_vap->va_mode &= ~(VSUID | VSGID); 165bfa108a0Sderaadt 166df930be7Sderaadt /* check access. for root we have to see if any exec bit on */ 1675ac46f4aSniklas if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0) 168df930be7Sderaadt goto bad1; 169df930be7Sderaadt if ((epp->ep_vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) { 170df930be7Sderaadt error = EACCES; 171df930be7Sderaadt goto bad1; 172df930be7Sderaadt } 173df930be7Sderaadt 174df930be7Sderaadt /* try to open it */ 1755ac46f4aSniklas if ((error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) != 0) 176df930be7Sderaadt goto bad1; 177df930be7Sderaadt 178d84dbf2eSart /* unlock vp, we need it unlocked from here */ 17936bb23f1Svisa VOP_UNLOCK(vp); 180d84dbf2eSart 181df930be7Sderaadt /* now we have the file, get the exec header */ 1825ac46f4aSniklas error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0, 183d84dbf2eSart UIO_SYSSPACE, 0, p->p_ucred, &resid, p); 1845ac46f4aSniklas if (error) 185df930be7Sderaadt goto bad2; 186df930be7Sderaadt epp->ep_hdrvalid = epp->ep_hdrlen - resid; 187df930be7Sderaadt 188df930be7Sderaadt /* 189df930be7Sderaadt * set up the vmcmds for creation of the process 190df930be7Sderaadt * address space 191df930be7Sderaadt */ 192df930be7Sderaadt error = ENOEXEC; 193df930be7Sderaadt for (i = 0; i < nexecs && error != 0; i++) { 194df930be7Sderaadt int newerror; 195df930be7Sderaadt 196df930be7Sderaadt if (execsw[i].es_check == NULL) 197df930be7Sderaadt continue; 198df930be7Sderaadt newerror = (*execsw[i].es_check)(p, epp); 199df930be7Sderaadt /* make sure the first "interesting" error code is saved. */ 200df930be7Sderaadt if (!newerror || error == ENOEXEC) 201df930be7Sderaadt error = newerror; 202df930be7Sderaadt if (epp->ep_flags & EXEC_DESTR && error != 0) 203bcfbf755Sniklas return (error); 204df930be7Sderaadt } 205df930be7Sderaadt if (!error) { 206df930be7Sderaadt /* check that entry point is sane */ 207ab30c277Spefo if (epp->ep_entry > VM_MAXUSER_ADDRESS) { 208df930be7Sderaadt error = ENOEXEC; 209ab30c277Spefo } 210df930be7Sderaadt 211df930be7Sderaadt /* check limits */ 212df930be7Sderaadt if ((epp->ep_tsize > MAXTSIZ) || 213edc99bcdSvisa (epp->ep_dsize > lim_cur(RLIMIT_DATA))) 214df930be7Sderaadt error = ENOMEM; 215df930be7Sderaadt 216df930be7Sderaadt if (!error) 217df930be7Sderaadt return (0); 218df930be7Sderaadt } 219df930be7Sderaadt 220df930be7Sderaadt /* 221df930be7Sderaadt * free any vmspace-creation commands, 222df930be7Sderaadt * and release their references 223df930be7Sderaadt */ 224df930be7Sderaadt kill_vmcmds(&epp->ep_vmcmds); 225df930be7Sderaadt 226df930be7Sderaadt bad2: 227df930be7Sderaadt /* 228d84dbf2eSart * close the vnode, free the pathname buf, and punt. 229df930be7Sderaadt */ 230df930be7Sderaadt vn_close(vp, FREAD, p->p_ucred, p); 231dbe27ba0Stedu pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf); 232bcfbf755Sniklas return (error); 233df930be7Sderaadt 234df930be7Sderaadt bad1: 235df930be7Sderaadt /* 236df930be7Sderaadt * free the namei pathname buffer, and put the vnode 237df930be7Sderaadt * (which we don't yet have open). 238df930be7Sderaadt */ 239dbe27ba0Stedu pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf); 240df930be7Sderaadt vput(vp); 241bcfbf755Sniklas return (error); 242df930be7Sderaadt } 243df930be7Sderaadt 244df930be7Sderaadt /* 245df930be7Sderaadt * exec system call 246df930be7Sderaadt */ 2475ac46f4aSniklas int 248158fb4f9Sjsg sys_execve(struct proc *p, void *v, register_t *retval) 249df930be7Sderaadt { 250586305f1Sart struct sys_execve_args /* { 25101b77f95Shenning syscallarg(const char *) path; 25201b77f95Shenning syscallarg(char *const *) argp; 25301b77f95Shenning syscallarg(char *const *) envp; 254df930be7Sderaadt } */ *uap = v; 255e20a449dStedu int error; 256df930be7Sderaadt struct exec_package pack; 257df930be7Sderaadt struct nameidata nid; 258df930be7Sderaadt struct vattr attr; 259df930be7Sderaadt struct ucred *cred = p->p_ucred; 260df930be7Sderaadt char *argp; 261d8434bb1Stholo char * const *cpp, *dp, *sp; 2625e0c3889Sguenther #ifdef KTRACE 2635e0c3889Sguenther char *env_start; 2645e0c3889Sguenther #endif 265bfb8af8fSguenther struct process *pr = p->p_p; 266df930be7Sderaadt long argc, envc; 2670233b312Sflorian size_t len, sgap, dstsize; 268cc576edfSmickey #ifdef MACHINE_STACK_GROWS_UP 269cc576edfSmickey size_t slen; 270cc576edfSmickey #endif 271df930be7Sderaadt char *stack; 272df930be7Sderaadt struct ps_strings arginfo; 273a2c764f6Sderaadt struct vmspace *vm = p->p_vmspace; 2747359b57aStedu struct vnode *otvp; 275df930be7Sderaadt 27614835c38Sclaudio /* 27714835c38Sclaudio * Get other threads to stop, if contested return ERESTART, 27814835c38Sclaudio * so the syscall is restarted after halting in userret. 27914835c38Sclaudio */ 28014835c38Sclaudio if (single_thread_set(p, SINGLE_UNWIND | SINGLE_DEEP)) 28114835c38Sclaudio return (ERESTART); 2822ea51a70Sguenther 283df930be7Sderaadt /* 284d5f75ac0Sart * Cheap solution to complicated problems. 285d5f75ac0Sart * Mark this process as "leave me alone, I'm execing". 286d5f75ac0Sart */ 2876b6f3ef9Sguenther atomic_setbits_int(&pr->ps_flags, PS_INEXEC); 288d5f75ac0Sart 28945573b1fSkettenis NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 290345a92b4Ssemarie nid.ni_pledge = PLEDGE_EXEC; 291e1a6e226Sbeck nid.ni_unveil = UNVEIL_EXEC; 292df930be7Sderaadt 293df930be7Sderaadt /* 294df930be7Sderaadt * initialize the fields of the exec package. 295df930be7Sderaadt */ 296d8434bb1Stholo pack.ep_name = (char *)SCARG(uap, path); 297176819c2Sart pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK); 298df930be7Sderaadt pack.ep_hdrlen = exec_maxhdrsz; 299df930be7Sderaadt pack.ep_hdrvalid = 0; 300df930be7Sderaadt pack.ep_ndp = &nid; 301c0c22b04Stedu pack.ep_interp = NULL; 302682e3c94Sguenther pack.ep_args = NULL; 303682e3c94Sguenther pack.ep_auxinfo = NULL; 3041bdf816eSart VMCMDSET_INIT(&pack.ep_vmcmds); 305df930be7Sderaadt pack.ep_vap = &attr; 306df930be7Sderaadt pack.ep_flags = 0; 307f0efa6a8Sderaadt pack.ep_pins = NULL; 308f0efa6a8Sderaadt pack.ep_npins = 0; 309df930be7Sderaadt 310df930be7Sderaadt /* see if we can run it. */ 311ab30c277Spefo if ((error = check_exec(p, &pack)) != 0) { 312df930be7Sderaadt goto freehdr; 313ab30c277Spefo } 314df930be7Sderaadt 315df930be7Sderaadt /* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */ 316df930be7Sderaadt 317df930be7Sderaadt /* allocate an argument buffer */ 318b324ced2Skettenis argp = km_alloc(NCARGS, &kv_exec, &kp_pageable, &kd_waitok); 319df930be7Sderaadt #ifdef DIAGNOSTIC 320b5099d50Snordin if (argp == NULL) 321df930be7Sderaadt panic("execve: argp == NULL"); 322df930be7Sderaadt #endif 323df930be7Sderaadt dp = argp; 324df930be7Sderaadt argc = 0; 325df930be7Sderaadt 3260233b312Sflorian /* 3270233b312Sflorian * Copy the fake args list, if there's one, freeing it as we go. 3280233b312Sflorian * exec_script_makecmds() allocates either 2 or 3 fake args bounded 3290233b312Sflorian * by MAXINTERP + MAXPATHLEN < NCARGS so no overflow can happen. 3300233b312Sflorian */ 331df930be7Sderaadt if (pack.ep_flags & EXEC_HASARGL) { 3320233b312Sflorian dstsize = NCARGS; 3330233b312Sflorian for(; pack.ep_fa[argc] != NULL; argc++) { 3340233b312Sflorian len = strlcpy(dp, pack.ep_fa[argc], dstsize); 3350233b312Sflorian len++; 3360233b312Sflorian dp += len; dstsize -= len; 3370233b312Sflorian if (pack.ep_fa[argc+1] != NULL) 3380233b312Sflorian free(pack.ep_fa[argc], M_EXEC, len); 3390233b312Sflorian else 3400233b312Sflorian free(pack.ep_fa[argc], M_EXEC, MAXPATHLEN); 341df930be7Sderaadt } 3420233b312Sflorian free(pack.ep_fa, M_EXEC, 4 * sizeof(char *)); 343df930be7Sderaadt pack.ep_flags &= ~EXEC_HASARGL; 344df930be7Sderaadt } 345df930be7Sderaadt 346df930be7Sderaadt /* Now get argv & environment */ 347df930be7Sderaadt if (!(cpp = SCARG(uap, argp))) { 348a5ceb13eSmickey error = EFAULT; 349df930be7Sderaadt goto bad; 350df930be7Sderaadt } 351df930be7Sderaadt 352df930be7Sderaadt if (pack.ep_flags & EXEC_SKIPARG) 353df930be7Sderaadt cpp++; 354df930be7Sderaadt 355df930be7Sderaadt while (1) { 356df930be7Sderaadt len = argp + ARG_MAX - dp; 3575ac46f4aSniklas if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) 358df930be7Sderaadt goto bad; 359df930be7Sderaadt if (!sp) 360df930be7Sderaadt break; 3615ac46f4aSniklas if ((error = copyinstr(sp, dp, len, &len)) != 0) { 362df930be7Sderaadt if (error == ENAMETOOLONG) 363df930be7Sderaadt error = E2BIG; 364df930be7Sderaadt goto bad; 365df930be7Sderaadt } 366df930be7Sderaadt dp += len; 367df930be7Sderaadt cpp++; 368df930be7Sderaadt argc++; 369df930be7Sderaadt } 370df930be7Sderaadt 37174212563Stedu /* must have at least one argument */ 37274212563Stedu if (argc == 0) { 37374212563Stedu error = EINVAL; 37474212563Stedu goto bad; 37574212563Stedu } 37674212563Stedu 3775e0c3889Sguenther #ifdef KTRACE 3785e0c3889Sguenther if (KTRPOINT(p, KTR_EXECARGS)) 3795e0c3889Sguenther ktrexec(p, KTR_EXECARGS, argp, dp - argp); 3805e0c3889Sguenther #endif 3815e0c3889Sguenther 382df930be7Sderaadt envc = 0; 383507f831cSmickey /* environment does not need to be there */ 3845ac46f4aSniklas if ((cpp = SCARG(uap, envp)) != NULL ) { 3855e0c3889Sguenther #ifdef KTRACE 3865e0c3889Sguenther env_start = dp; 3875e0c3889Sguenther #endif 388df930be7Sderaadt while (1) { 389df930be7Sderaadt len = argp + ARG_MAX - dp; 3905ac46f4aSniklas if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) 391df930be7Sderaadt goto bad; 392df930be7Sderaadt if (!sp) 393df930be7Sderaadt break; 3945ac46f4aSniklas if ((error = copyinstr(sp, dp, len, &len)) != 0) { 395df930be7Sderaadt if (error == ENAMETOOLONG) 396df930be7Sderaadt error = E2BIG; 397df930be7Sderaadt goto bad; 398df930be7Sderaadt } 399df930be7Sderaadt dp += len; 400df930be7Sderaadt cpp++; 401df930be7Sderaadt envc++; 402df930be7Sderaadt } 4035e0c3889Sguenther 4045e0c3889Sguenther #ifdef KTRACE 4055e0c3889Sguenther if (KTRPOINT(p, KTR_EXECENV)) 4065e0c3889Sguenther ktrexec(p, KTR_EXECENV, env_start, dp - env_start); 4075e0c3889Sguenther #endif 408df930be7Sderaadt } 409df930be7Sderaadt 410b8736dc1Sderaadt dp = (char *)(((long)dp + _STACKALIGNBYTES) & ~_STACKALIGNBYTES); 411df930be7Sderaadt 4122bda40dcSmiod /* 4132bda40dcSmiod * If we have enabled random stackgap, the stack itself has already 4142bda40dcSmiod * been moved from a random location, but is still aligned to a page 4152bda40dcSmiod * boundary. Provide the lower bits of random placement now. 4162bda40dcSmiod */ 4172f033923Sguenther if (stackgap_random == 0) { 4182f033923Sguenther sgap = 0; 4192f033923Sguenther } else { 4202f033923Sguenther sgap = arc4random() & PAGE_MASK; 421b8736dc1Sderaadt sgap = (sgap + _STACKALIGNBYTES) & ~_STACKALIGNBYTES; 422b8736dc1Sderaadt } 423b8736dc1Sderaadt 424df930be7Sderaadt /* Now check if args & environ fit into new stack */ 425b702d795Sguenther len = ((argc + envc + 2 + ELF_AUX_WORDS) * sizeof(char *) + 4264a5480feSart sizeof(long) + dp + sgap + sizeof(struct ps_strings)) - argp; 427df930be7Sderaadt 428b8736dc1Sderaadt len = (len + _STACKALIGNBYTES) &~ _STACKALIGNBYTES; 429df930be7Sderaadt 430df930be7Sderaadt if (len > pack.ep_ssize) { /* in effect, compare to initial limit */ 431df930be7Sderaadt error = ENOMEM; 432df930be7Sderaadt goto bad; 433df930be7Sderaadt } 434df930be7Sderaadt 435df930be7Sderaadt /* adjust "active stack depth" for process VSZ */ 436df930be7Sderaadt pack.ep_ssize = len; /* maybe should go elsewhere, but... */ 437df930be7Sderaadt 43886607369Sart /* 4392ea51a70Sguenther * we're committed: any further errors will kill the process, so 4402ea51a70Sguenther * kill the other threads now. 4412ea51a70Sguenther */ 442a556b217Sclaudio single_thread_set(p, SINGLE_EXIT); 4432ea51a70Sguenther 4442ea51a70Sguenther /* 44586607369Sart * Prepare vmspace for remapping. Note that uvmspace_exec can replace 446a9872addSguenther * ps_vmspace! 44786607369Sart */ 448cac1bff1Sart uvmspace_exec(p, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); 449df930be7Sderaadt 450924be113Sguenther vm = pr->ps_vmspace; 451df930be7Sderaadt /* Now map address space */ 452ff3fdef1Skettenis vm->vm_taddr = (char *)trunc_page(pack.ep_taddr); 453ff3fdef1Skettenis vm->vm_tsize = atop(round_page(pack.ep_taddr + pack.ep_tsize) - 454ff3fdef1Skettenis trunc_page(pack.ep_taddr)); 455ff3fdef1Skettenis vm->vm_daddr = (char *)trunc_page(pack.ep_daddr); 456ff3fdef1Skettenis vm->vm_dsize = atop(round_page(pack.ep_daddr + pack.ep_dsize) - 457ff3fdef1Skettenis trunc_page(pack.ep_daddr)); 4580ebeee85Sderaadt vm->vm_dused = 0; 45976d52da2Smartin vm->vm_ssize = atop(round_page(pack.ep_ssize)); 460df930be7Sderaadt vm->vm_maxsaddr = (char *)pack.ep_maxsaddr; 461d9040bf8Smickey vm->vm_minsaddr = (char *)pack.ep_minsaddr; 462df930be7Sderaadt 463df930be7Sderaadt /* create the new process's VM space by running the vmcmds */ 464df930be7Sderaadt #ifdef DIAGNOSTIC 465df930be7Sderaadt if (pack.ep_vmcmds.evs_used == 0) 466df930be7Sderaadt panic("execve: no vmcmds"); 467df930be7Sderaadt #endif 4681e04e351Sart error = exec_process_vmcmds(p, &pack); 469df930be7Sderaadt 470df930be7Sderaadt /* if an error happened, deallocate and punt */ 471df930be7Sderaadt if (error) 472df930be7Sderaadt goto exec_abort; 473df930be7Sderaadt 47456b6d613Skettenis #ifdef MACHINE_STACK_GROWS_UP 4757180d9eaSmiod pr->ps_strings = (vaddr_t)vm->vm_maxsaddr + sgap; 47656b6d613Skettenis if (uvm_map_protect(&vm->vm_map, (vaddr_t)vm->vm_maxsaddr, 4774c8ae43bSderaadt trunc_page(pr->ps_strings), PROT_NONE, 0, TRUE, FALSE)) 47856b6d613Skettenis goto exec_abort; 47956b6d613Skettenis #else 4807180d9eaSmiod pr->ps_strings = (vaddr_t)vm->vm_minsaddr - sizeof(arginfo) - sgap; 48156b6d613Skettenis if (uvm_map_protect(&vm->vm_map, 48256b6d613Skettenis round_page(pr->ps_strings + sizeof(arginfo)), 4834c8ae43bSderaadt (vaddr_t)vm->vm_minsaddr, PROT_NONE, 0, TRUE, FALSE)) 48456b6d613Skettenis goto exec_abort; 48556b6d613Skettenis #endif 48656b6d613Skettenis 4876c87c9e2Sbluhm memset(&arginfo, 0, sizeof(arginfo)); 4886c87c9e2Sbluhm 489df930be7Sderaadt /* remember information about the process */ 490df930be7Sderaadt arginfo.ps_nargvstr = argc; 491df930be7Sderaadt arginfo.ps_nenvstr = envc; 492df930be7Sderaadt 493910e6419Smickey #ifdef MACHINE_STACK_GROWS_UP 4947180d9eaSmiod stack = (char *)vm->vm_maxsaddr + sizeof(arginfo) + sgap; 495f18df0c5Skettenis slen = len - sizeof(arginfo) - sgap; 496910e6419Smickey #else 4977180d9eaSmiod stack = (char *)(vm->vm_minsaddr - len); 498910e6419Smickey #endif 499df930be7Sderaadt /* Now copy argc, args & environ to new stack */ 500682e3c94Sguenther if (!copyargs(&pack, &arginfo, stack, argp)) 501df930be7Sderaadt goto exec_abort; 502df930be7Sderaadt 5034ec5462fSmbuhl pr->ps_auxinfo = (vaddr_t)pack.ep_auxinfo; 5044ec5462fSmbuhl 505df930be7Sderaadt /* copy out the process's ps_strings structure */ 506a78264c4Skettenis if (copyout(&arginfo, (char *)pr->ps_strings, sizeof(arginfo))) 507df930be7Sderaadt goto exec_abort; 508df930be7Sderaadt 509f0efa6a8Sderaadt free(pr->ps_pin.pn_pins, M_PINSYSCALL, 510f0efa6a8Sderaadt pr->ps_pin.pn_npins * sizeof(u_int)); 511f0efa6a8Sderaadt if (pack.ep_npins) { 512f0efa6a8Sderaadt pr->ps_pin.pn_start = pack.ep_pinstart; 513f0efa6a8Sderaadt pr->ps_pin.pn_end = pack.ep_pinend; 514f0efa6a8Sderaadt pr->ps_pin.pn_pins = pack.ep_pins; 515f0efa6a8Sderaadt pack.ep_pins = NULL; 516f0efa6a8Sderaadt pr->ps_pin.pn_npins = pack.ep_npins; 517f0efa6a8Sderaadt } else { 518f0efa6a8Sderaadt pr->ps_pin.pn_start = pr->ps_pin.pn_end = 0; 519f0efa6a8Sderaadt pr->ps_pin.pn_pins = NULL; 520f0efa6a8Sderaadt pr->ps_pin.pn_npins = 0; 521f0efa6a8Sderaadt } 522f0efa6a8Sderaadt if (pr->ps_libcpin.pn_pins) { 523f0efa6a8Sderaadt free(pr->ps_libcpin.pn_pins, M_PINSYSCALL, 524f0efa6a8Sderaadt pr->ps_libcpin.pn_npins * sizeof(u_int)); 525f0efa6a8Sderaadt pr->ps_libcpin.pn_start = pr->ps_libcpin.pn_end = 0; 526f0efa6a8Sderaadt pr->ps_libcpin.pn_pins = NULL; 527f0efa6a8Sderaadt pr->ps_libcpin.pn_npins = 0; 528f0efa6a8Sderaadt } 529f0efa6a8Sderaadt 53018914fdfSguenther stopprofclock(pr); /* stop profiling */ 531df930be7Sderaadt fdcloseexec(p); /* handle close on exec */ 532611924b3Smiod execsigs(p); /* reset caught signals */ 533c6319251Sguenther TCB_SET(p, NULL); /* reset the TCB address */ 534440e6fe6Sguenther pr->ps_kbind_addr = 0; /* reset the kbind bits */ 535440e6fe6Sguenther pr->ps_kbind_cookie = 0; 5367730d1d9Sderaadt arc4random_buf(&pr->ps_sigcookie, sizeof pr->ps_sigcookie); 537df930be7Sderaadt 538df930be7Sderaadt /* set command name & other accounting info */ 5398fda72b7Sguenther memset(pr->ps_comm, 0, sizeof(pr->ps_comm)); 540633fc60bSderaadt strlcpy(pr->ps_comm, nid.ni_cnd.cn_nameptr, sizeof(pr->ps_comm)); 5410839b846Smikeb pr->ps_acflag &= ~AFORK; 542df930be7Sderaadt 543cf6677a6Sguenther /* record proc's vnode, for use by sysctl */ 5444ab8ed70Sguenther otvp = pr->ps_textvp; 545627b2c48Sthib vref(pack.ep_vp); 5464ab8ed70Sguenther pr->ps_textvp = pack.ep_vp; 5477359b57aStedu if (otvp) 5487359b57aStedu vrele(otvp); 549df930be7Sderaadt 550a8701c59Sguenther if (pack.ep_flags & EXEC_NOBTCFI) 551a8701c59Sguenther atomic_setbits_int(&p->p_p->ps_flags, PS_NOBTCFI); 552a8701c59Sguenther else 553a8701c59Sguenther atomic_clearbits_int(&p->p_p->ps_flags, PS_NOBTCFI); 554a8701c59Sguenther 555e2590abeSguenther atomic_setbits_int(&pr->ps_flags, PS_EXEC); 556c0ce47d9Sguenther if (pr->ps_flags & PS_PPWAIT) { 557c0ce47d9Sguenther atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT); 558c0ce47d9Sguenther atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT); 559bfb8af8fSguenther wakeup(pr->ps_pptr); 560df930be7Sderaadt } 561df930be7Sderaadt 562df930be7Sderaadt /* 563855755d9Smillert * If process does execve() while it has a mismatched real, 564bfb8af8fSguenther * effective, or saved uid/gid, we set PS_SUGIDEXEC. 56525b40de6Sderaadt */ 566d559b8cbSguenther if (cred->cr_uid != cred->cr_ruid || 567d559b8cbSguenther cred->cr_uid != cred->cr_svuid || 568d559b8cbSguenther cred->cr_gid != cred->cr_rgid || 569d559b8cbSguenther cred->cr_gid != cred->cr_svgid) 570bfb8af8fSguenther atomic_setbits_int(&pr->ps_flags, PS_SUGIDEXEC); 571855755d9Smillert else 572bfb8af8fSguenther atomic_clearbits_int(&pr->ps_flags, PS_SUGIDEXEC); 57325b40de6Sderaadt 5744ea7ed56Sderaadt if (pr->ps_flags & PS_EXECPLEDGE) { 5754ea7ed56Sderaadt pr->ps_pledge = pr->ps_execpledge; 5764ea7ed56Sderaadt atomic_setbits_int(&pr->ps_flags, PS_PLEDGE); 5774ea7ed56Sderaadt } else { 578df174574Sderaadt atomic_clearbits_int(&pr->ps_flags, PS_PLEDGE); 5794ea7ed56Sderaadt pr->ps_pledge = 0; 5808b23add8Sbeck /* XXX XXX XXX XXX */ 5818b23add8Sbeck /* Clear our unveil paths out so the child 5828b23add8Sbeck * starts afresh 5838b23add8Sbeck */ 5848b23add8Sbeck unveil_destroy(pr); 5858b23add8Sbeck pr->ps_uvdone = 0; 5864ea7ed56Sderaadt } 587609289baSderaadt 58825b40de6Sderaadt /* 589df930be7Sderaadt * deal with set[ug]id. 59051f754c1Sart * MNT_NOEXEC has already been used to disable s[ug]id. 591df930be7Sderaadt */ 59251f754c1Sart if ((attr.va_mode & (VSUID | VSGID)) && proc_cansugid(p)) { 593bbf7a176Sderaadt int i; 594bbf7a176Sderaadt 595bfb8af8fSguenther atomic_setbits_int(&pr->ps_flags, PS_SUGID|PS_SUGIDEXEC); 59651f754c1Sart 597df930be7Sderaadt #ifdef KTRACE 598df930be7Sderaadt /* 599df930be7Sderaadt * If process is being ktraced, turn off - unless 600df930be7Sderaadt * root set it. 601df930be7Sderaadt */ 602a2e04e14Sguenther if (pr->ps_tracevp && !(pr->ps_traceflag & KTRFAC_ROOT)) 603a2e04e14Sguenther ktrcleartrace(pr); 604df930be7Sderaadt #endif 605d559b8cbSguenther p->p_ucred = cred = crcopy(cred); 606df930be7Sderaadt if (attr.va_mode & VSUID) 607d559b8cbSguenther cred->cr_uid = attr.va_uid; 608df930be7Sderaadt if (attr.va_mode & VSGID) 609d559b8cbSguenther cred->cr_gid = attr.va_gid; 610bbf7a176Sderaadt 611bbf7a176Sderaadt /* 612bba8c139Sderaadt * For set[ug]id processes, a few caveats apply to 613bba8c139Sderaadt * stdin, stdout, and stderr. 614bbf7a176Sderaadt */ 615638f0017Sguenther error = 0; 616638f0017Sguenther fdplock(p->p_fd); 617bbf7a176Sderaadt for (i = 0; i < 3; i++) { 618c3315ca6Sderaadt struct file *fp = NULL; 619c3315ca6Sderaadt 620af97e5cfSart /* 621af97e5cfSart * NOTE - This will never return NULL because of 6222addf348Sjmc * immature fds. The file descriptor table is not 623af97e5cfSart * shared because we're suid. 624af97e5cfSart */ 625af97e5cfSart fp = fd_getfile(p->p_fd, i); 626c3315ca6Sderaadt 627c3315ca6Sderaadt /* 628c3315ca6Sderaadt * Ensure that stdin, stdout, and stderr are already 629c3315ca6Sderaadt * allocated. We do not want userland to accidentally 630c3315ca6Sderaadt * allocate descriptors in this range which has implied 631c3315ca6Sderaadt * meaning to libc. 632c3315ca6Sderaadt */ 633c3315ca6Sderaadt if (fp == NULL) { 634c3315ca6Sderaadt short flags = FREAD | (i == 0 ? 0 : FWRITE); 635faa48718Sart struct vnode *vp; 636bbf7a176Sderaadt int indx; 63758d9451eSart 638cd6537e7Smpi if ((error = falloc(p, &fp, &indx)) != 0) 639638f0017Sguenther break; 640faa48718Sart #ifdef DIAGNOSTIC 641faa48718Sart if (indx != i) 642faa48718Sart panic("sys_execve: falloc indx != i"); 643faa48718Sart #endif 644faa48718Sart if ((error = cdevvp(getnulldev(), &vp)) != 0) { 645bb720fc6Sprovos fdremove(p->p_fd, indx); 64643c6a78bSart closef(fp, p); 647638f0017Sguenther break; 648bbf7a176Sderaadt } 649d559b8cbSguenther if ((error = VOP_OPEN(vp, flags, cred, p)) != 0) { 650faa48718Sart fdremove(p->p_fd, indx); 65143c6a78bSart closef(fp, p); 652faa48718Sart vrele(vp); 653638f0017Sguenther break; 654faa48718Sart } 655faa48718Sart if (flags & FWRITE) 656faa48718Sart vp->v_writecount++; 65758d9451eSart fp->f_flag = flags; 658bbf7a176Sderaadt fp->f_type = DTYPE_VNODE; 659bbf7a176Sderaadt fp->f_ops = &vnops; 660faa48718Sart fp->f_data = (caddr_t)vp; 661cd6537e7Smpi fdinsert(p->p_fd, indx, 0, fp); 662bbf7a176Sderaadt } 663cd6537e7Smpi FRELE(fp, p); 664f695adb7Smpi } 665638f0017Sguenther fdpunlock(p->p_fd); 666638f0017Sguenther if (error) 667638f0017Sguenther goto exec_abort; 66825b40de6Sderaadt } else 669bfb8af8fSguenther atomic_clearbits_int(&pr->ps_flags, PS_SUGID); 670d559b8cbSguenther 671a9ddc286Sguenther /* 672a9ddc286Sguenther * Reset the saved ugids and update the process's copy of the 673a9ddc286Sguenther * creds if the creds have been changed 674a9ddc286Sguenther */ 675d559b8cbSguenther if (cred->cr_uid != cred->cr_svuid || 676d559b8cbSguenther cred->cr_gid != cred->cr_svgid) { 677d559b8cbSguenther /* make sure we have unshared ucreds */ 678d559b8cbSguenther p->p_ucred = cred = crcopy(cred); 679d559b8cbSguenther cred->cr_svuid = cred->cr_uid; 680d559b8cbSguenther cred->cr_svgid = cred->cr_gid; 681d559b8cbSguenther } 682df930be7Sderaadt 683a9ddc286Sguenther if (pr->ps_ucred != cred) { 684a9ddc286Sguenther struct ucred *ocred; 685a9ddc286Sguenther 686a9ddc286Sguenther ocred = pr->ps_ucred; 687a9ddc286Sguenther crhold(cred); 688a9ddc286Sguenther pr->ps_ucred = cred; 689a9ddc286Sguenther crfree(ocred); 690a9ddc286Sguenther } 691a9ddc286Sguenther 692bfb8af8fSguenther if (pr->ps_flags & PS_SUGIDEXEC) { 693ae96cbdaScheloha cancel_all_itimers(); 69421b2622bSderaadt } 69521b2622bSderaadt 6967b36c281Sguenther /* reset CPU time usage for the thread, but not the process */ 6977b36c281Sguenther timespecclear(&p->p_tu.tu_runtime); 6987b36c281Sguenther p->p_tu.tu_uticks = p->p_tu.tu_sticks = p->p_tu.tu_iticks = 0; 699241d6723Sclaudio p->p_tu.tu_gen = 0; 7007b36c281Sguenther 701cef5a146Sguenther memset(p->p_name, 0, sizeof p->p_name); 702cef5a146Sguenther 703b324ced2Skettenis km_free(argp, NCARGS, &kv_exec, &kp_pageable); 704df930be7Sderaadt 705dbe27ba0Stedu pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); 706d84dbf2eSart vn_close(pack.ep_vp, FREAD, cred, p); 707df930be7Sderaadt 7081a12e8a7Sprovos /* 7091a12e8a7Sprovos * notify others that we exec'd 7101a12e8a7Sprovos */ 7110747e3d2Sclaudio knote(&pr->ps_klist, NOTE_EXEC); 7121a12e8a7Sprovos 7134ed6f7c2Sguenther /* map the process's timekeep page, needs to be before exec_elf_fixup */ 714d82e6535Spirofti if (exec_timekeep_map(pr)) 715d82e6535Spirofti goto free_pack_abort; 716d82e6535Spirofti 717df930be7Sderaadt /* setup new registers and do misc. setup. */ 7184ed6f7c2Sguenther if (exec_elf_fixup(p, &pack) != 0) 719ab30c277Spefo goto free_pack_abort; 720910e6419Smickey #ifdef MACHINE_STACK_GROWS_UP 7211b4a394fSguenther setregs(p, &pack, (u_long)stack + slen, &arginfo); 722910e6419Smickey #else 7231b4a394fSguenther setregs(p, &pack, (u_long)stack, &arginfo); 724910e6419Smickey #endif 725df930be7Sderaadt 7264a5480feSart /* map the process's signal trampoline code */ 7275a72e03eSguenther if (exec_sigcode_map(pr)) 728c0c22b04Stedu goto free_pack_abort; 7294a5480feSart 7304c0d1b1bSmiod #ifdef __HAVE_EXEC_MD_MAP 7314c0d1b1bSmiod /* perform md specific mappings that process might need */ 7324c0d1b1bSmiod if (exec_md_map(p, &pack)) 7334c0d1b1bSmiod goto free_pack_abort; 7344c0d1b1bSmiod #endif 7354c0d1b1bSmiod 7366b6f3ef9Sguenther if (pr->ps_flags & PS_TRACED) 737df930be7Sderaadt psignal(p, SIGTRAP); 738df930be7Sderaadt 7397da957a5Sderaadt free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); 740df930be7Sderaadt 741d9f343eeSderaadt p->p_descfd = 255; 742d9f343eeSderaadt if ((pack.ep_flags & EXEC_HASFD) && pack.ep_fd < 255) 743d9f343eeSderaadt p->p_descfd = pack.ep_fd; 744d9f343eeSderaadt 745f68ce565Sderaadt if (pack.ep_flags & EXEC_WXNEEDED) 7469648c32bSanton atomic_setbits_int(&p->p_p->ps_flags, PS_WXNEEDED); 747131b88b7Sjca else 7489648c32bSanton atomic_clearbits_int(&p->p_p->ps_flags, PS_WXNEEDED); 749f68ce565Sderaadt 7506b6f3ef9Sguenther atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); 751*d479e871Sclaudio single_thread_clear(p); 7525c025fc6Smarius 7531b4a394fSguenther /* setregs() sets up all the registers, so just 'return' */ 7541b4a394fSguenther return EJUSTRETURN; 755df930be7Sderaadt 756df930be7Sderaadt bad: 757df930be7Sderaadt /* free the vmspace-creation commands, and release their references */ 758df930be7Sderaadt kill_vmcmds(&pack.ep_vmcmds); 759df930be7Sderaadt /* kill any opened file descriptor, if necessary */ 760df930be7Sderaadt if (pack.ep_flags & EXEC_HASFD) { 761df930be7Sderaadt pack.ep_flags &= ~EXEC_HASFD; 762638f0017Sguenther fdplock(p->p_fd); 7638994f64aSvisa /* fdrelease unlocks p->p_fd. */ 764df930be7Sderaadt (void) fdrelease(p, pack.ep_fd); 765df930be7Sderaadt } 766c0c22b04Stedu if (pack.ep_interp != NULL) 767335c12deSmickey pool_put(&namei_pool, pack.ep_interp); 768682e3c94Sguenther free(pack.ep_args, M_TEMP, sizeof *pack.ep_args); 769f0efa6a8Sderaadt free(pack.ep_pins, M_PINSYSCALL, pack.ep_npins * sizeof(u_int)); 770df930be7Sderaadt /* close and put the exec'd file */ 771d84dbf2eSart vn_close(pack.ep_vp, FREAD, cred, p); 772dbe27ba0Stedu pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); 773b324ced2Skettenis km_free(argp, NCARGS, &kv_exec, &kp_pageable); 774df930be7Sderaadt 775df930be7Sderaadt freehdr: 7767da957a5Sderaadt free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); 7776b6f3ef9Sguenther atomic_clearbits_int(&pr->ps_flags, PS_INEXEC); 778*d479e871Sclaudio single_thread_clear(p); 779a792ab75Sart 780bcfbf755Sniklas return (error); 781df930be7Sderaadt 782df930be7Sderaadt exec_abort: 783df930be7Sderaadt /* 784df930be7Sderaadt * the old process doesn't exist anymore. exit gracefully. 785df930be7Sderaadt * get rid of the (new) address space we have created, if any, get rid 786df930be7Sderaadt * of our namei data and vnode, and exit noting failure 787df930be7Sderaadt */ 788782069b1Smpi uvm_unmap(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); 789c0c22b04Stedu if (pack.ep_interp != NULL) 790335c12deSmickey pool_put(&namei_pool, pack.ep_interp); 791682e3c94Sguenther free(pack.ep_args, M_TEMP, sizeof *pack.ep_args); 792dbe27ba0Stedu pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); 793d84dbf2eSart vn_close(pack.ep_vp, FREAD, cred, p); 794b324ced2Skettenis km_free(argp, NCARGS, &kv_exec, &kp_pageable); 795ab30c277Spefo 796ab30c277Spefo free_pack_abort: 7977da957a5Sderaadt free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); 798381e34d2Sguenther exit1(p, 0, SIGABRT, EXIT_NORMAL); 799df930be7Sderaadt /* NOTREACHED */ 800df930be7Sderaadt } 801df930be7Sderaadt 802df930be7Sderaadt 803682e3c94Sguenther int 804158fb4f9Sjsg copyargs(struct exec_package *pack, struct ps_strings *arginfo, void *stack, 805158fb4f9Sjsg void *argp) 806df930be7Sderaadt { 807df930be7Sderaadt char **cpp = stack; 808df930be7Sderaadt char *dp, *sp; 809df930be7Sderaadt size_t len; 810df930be7Sderaadt void *nullp = NULL; 811d2b5d78fSart long argc = arginfo->ps_nargvstr; 812df930be7Sderaadt int envc = arginfo->ps_nenvstr; 813df930be7Sderaadt 814df930be7Sderaadt if (copyout(&argc, cpp++, sizeof(argc))) 815682e3c94Sguenther return (0); 816df930be7Sderaadt 817b702d795Sguenther dp = (char *) (cpp + argc + envc + 2 + ELF_AUX_WORDS); 818df930be7Sderaadt sp = argp; 819df930be7Sderaadt 820df930be7Sderaadt /* XXX don't copy them out, remap them! */ 821df930be7Sderaadt arginfo->ps_argvstr = cpp; /* remember location of argv for later */ 822df930be7Sderaadt 823df930be7Sderaadt for (; --argc >= 0; sp += len, dp += len) 824df930be7Sderaadt if (copyout(&dp, cpp++, sizeof(dp)) || 825df930be7Sderaadt copyoutstr(sp, dp, ARG_MAX, &len)) 826682e3c94Sguenther return (0); 827df930be7Sderaadt 828df930be7Sderaadt if (copyout(&nullp, cpp++, sizeof(nullp))) 829682e3c94Sguenther return (0); 830df930be7Sderaadt 831df930be7Sderaadt arginfo->ps_envstr = cpp; /* remember location of envp for later */ 832df930be7Sderaadt 833df930be7Sderaadt for (; --envc >= 0; sp += len, dp += len) 834df930be7Sderaadt if (copyout(&dp, cpp++, sizeof(dp)) || 835df930be7Sderaadt copyoutstr(sp, dp, ARG_MAX, &len)) 836682e3c94Sguenther return (0); 837df930be7Sderaadt 838df930be7Sderaadt if (copyout(&nullp, cpp++, sizeof(nullp))) 839682e3c94Sguenther return (0); 840df930be7Sderaadt 841682e3c94Sguenther /* if this process needs auxinfo, note where to place it */ 842682e3c94Sguenther if (pack->ep_args != NULL) 843682e3c94Sguenther pack->ep_auxinfo = cpp; 844682e3c94Sguenther 845682e3c94Sguenther return (1); 846df930be7Sderaadt } 8474a5480feSart 8484a5480feSart int 8495a72e03eSguenther exec_sigcode_map(struct process *pr) 8504a5480feSart { 8515a72e03eSguenther extern char sigcode[], esigcode[], sigcoderet[]; 8524a5480feSart vsize_t sz; 8534a5480feSart 8545a72e03eSguenther sz = (vaddr_t)esigcode - (vaddr_t)sigcode; 8554a5480feSart 8564a5480feSart /* 8575a72e03eSguenther * If we don't have a sigobject yet, create one. 8584a5480feSart * 8594a5480feSart * sigobject is an anonymous memory object (just like SYSV shared 8604a5480feSart * memory) that we keep a permanent reference to and that we map 8614a5480feSart * in all processes that need this sigcode. The creation is simple, 8624a5480feSart * we create an object, add a permanent reference to it, map it in 8631db99e90Sderaadt * kernel space, copy out the sigcode to it and unmap it. Then we map 8641db99e90Sderaadt * it with PROT_EXEC into the process just the way sys_mmap would map it. 8654a5480feSart */ 8665a72e03eSguenther if (sigobject == NULL) { 867b983598cSderaadt extern int sigfillsiz; 868b983598cSderaadt extern u_char sigfill[]; 869d5ee67c8Sderaadt size_t off, left; 8704a5480feSart vaddr_t va; 8714a5480feSart int r; 8724a5480feSart 8735a72e03eSguenther sigobject = uao_create(sz, 0); 8745a72e03eSguenther uao_reference(sigobject); /* permanent reference */ 8754a5480feSart 8765a72e03eSguenther if ((r = uvm_map(kernel_map, &va, round_page(sz), sigobject, 8771e8cdc2eSderaadt 0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, 87815cd8707Sguenther MAP_INHERIT_SHARE, MADV_RANDOM, 0)))) { 8795a72e03eSguenther uao_detach(sigobject); 8804a5480feSart return (ENOMEM); 8814a5480feSart } 882b983598cSderaadt 883d5ee67c8Sderaadt for (off = 0, left = round_page(sz); left != 0; 884d5ee67c8Sderaadt off += sigfillsiz) { 885d5ee67c8Sderaadt size_t chunk = ulmin(left, sigfillsiz); 886d5ee67c8Sderaadt memcpy((caddr_t)va + off, sigfill, chunk); 887d5ee67c8Sderaadt left -= chunk; 888d5ee67c8Sderaadt } 8895a72e03eSguenther memcpy((caddr_t)va, sigcode, sz); 89013f0bae7Skettenis 89113f0bae7Skettenis (void) uvm_map_protect(kernel_map, va, round_page(sz), 89213f0bae7Skettenis PROT_READ, 0, FALSE, FALSE); 89313f0bae7Skettenis sigcode_va = va; 89413f0bae7Skettenis sigcode_sz = round_page(sz); 8954a5480feSart } 8964a5480feSart 897924be113Sguenther pr->ps_sigcode = 0; /* no hint */ 8985a72e03eSguenther uao_reference(sigobject); 899924be113Sguenther if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_sigcode, round_page(sz), 9001db99e90Sderaadt sigobject, 0, 0, UVM_MAPFLAG(PROT_EXEC, 90112ccc845Skettenis PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_COPY, 90230d20579Sderaadt MADV_RANDOM, UVM_FLAG_COPYONW))) { 9035a72e03eSguenther uao_detach(sigobject); 9044a5480feSart return (ENOMEM); 9054a5480feSart } 9068db818c7Sderaadt uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_sigcode, 9071c71e4e1Sderaadt pr->ps_sigcode + round_page(sz), 1); 9084a5480feSart 9097730d1d9Sderaadt /* Calculate PC at point of sigreturn entry */ 9105a72e03eSguenther pr->ps_sigcoderet = pr->ps_sigcode + (sigcoderet - sigcode); 9117730d1d9Sderaadt 9124a5480feSart return (0); 9134a5480feSart } 914d82e6535Spirofti 915d82e6535Spirofti int 916d82e6535Spirofti exec_timekeep_map(struct process *pr) 917d82e6535Spirofti { 9186a3d01b2Skettenis size_t timekeep_sz = round_page(sizeof(struct timekeep)); 919d82e6535Spirofti 920d82e6535Spirofti /* 921f231ff59Sguenther * Similar to the sigcode object 922d82e6535Spirofti */ 923d82e6535Spirofti if (timekeep_object == NULL) { 924d82e6535Spirofti vaddr_t va = 0; 925d82e6535Spirofti 926d82e6535Spirofti timekeep_object = uao_create(timekeep_sz, 0); 927d82e6535Spirofti uao_reference(timekeep_object); 928d82e6535Spirofti 9296a3d01b2Skettenis if (uvm_map(kernel_map, &va, timekeep_sz, timekeep_object, 930d82e6535Spirofti 0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, 931d82e6535Spirofti MAP_INHERIT_SHARE, MADV_RANDOM, 0))) { 932d82e6535Spirofti uao_detach(timekeep_object); 9336a3d01b2Skettenis timekeep_object = NULL; 9346a3d01b2Skettenis return (ENOMEM); 9356a3d01b2Skettenis } 9366a3d01b2Skettenis if (uvm_fault_wire(kernel_map, va, va + timekeep_sz, 9376a3d01b2Skettenis PROT_READ | PROT_WRITE)) { 9386a3d01b2Skettenis uvm_unmap(kernel_map, va, va + timekeep_sz); 9396a3d01b2Skettenis uao_detach(timekeep_object); 9406a3d01b2Skettenis timekeep_object = NULL; 941d82e6535Spirofti return (ENOMEM); 942d82e6535Spirofti } 943d82e6535Spirofti 944d82e6535Spirofti timekeep = (struct timekeep *)va; 945d82e6535Spirofti timekeep->tk_version = TK_VERSION; 946d82e6535Spirofti } 947d82e6535Spirofti 948d82e6535Spirofti pr->ps_timekeep = 0; /* no hint */ 949d82e6535Spirofti uao_reference(timekeep_object); 9501502f498Snaddy if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, timekeep_sz, 951d82e6535Spirofti timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ, 952d82e6535Spirofti MAP_INHERIT_COPY, MADV_RANDOM, 0))) { 953d82e6535Spirofti uao_detach(timekeep_object); 954d82e6535Spirofti return (ENOMEM); 955d82e6535Spirofti } 9568db818c7Sderaadt uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_timekeep, 9571c71e4e1Sderaadt pr->ps_timekeep + timekeep_sz, 1); 958d82e6535Spirofti 959d82e6535Spirofti return (0); 960d82e6535Spirofti } 961