1 /* $OpenBSD: kern_exec.c,v 1.55 2001/08/18 03:32:16 art Exp $ */ 2 /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ 3 4 /*- 5 * Copyright (C) 1993, 1994 Christopher G. Demetriou 6 * Copyright (C) 1992 Wolfgang Solfrank. 7 * Copyright (C) 1992 TooLs GmbH. 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by TooLs GmbH. 21 * 4. The name of TooLs GmbH may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/filedesc.h> 39 #include <sys/kernel.h> 40 #include <sys/proc.h> 41 #include <sys/mount.h> 42 #include <sys/malloc.h> 43 #include <sys/namei.h> 44 #include <sys/vnode.h> 45 #include <sys/file.h> 46 #include <sys/acct.h> 47 #include <sys/exec.h> 48 #include <sys/ktrace.h> 49 #include <sys/resourcevar.h> 50 #include <sys/wait.h> 51 #include <sys/mman.h> 52 #include <sys/signalvar.h> 53 #include <sys/stat.h> 54 #include <sys/conf.h> 55 #ifdef SYSVSHM 56 #include <sys/shm.h> 57 #endif 58 59 #include <sys/syscallargs.h> 60 61 #include <vm/vm.h> 62 #include <vm/vm_kern.h> 63 64 #include <uvm/uvm_extern.h> 65 66 #include <machine/cpu.h> 67 #include <machine/reg.h> 68 69 #include <dev/rndvar.h> 70 71 /* 72 * stackgap_random specifies if the stackgap should have a random size added 73 * to it. Must be a n^2. If non-zero, the stack gap will be calculated as: 74 * (arc4random() * ALIGNBYTES) & (stackgap_random - 1) + STACKGAPLEN. 75 */ 76 int stackgap_random; 77 78 /* 79 * check exec: 80 * given an "executable" described in the exec package's namei info, 81 * see what we can do with it. 82 * 83 * ON ENTRY: 84 * exec package with appropriate namei info 85 * proc pointer of exec'ing proc 86 * NO SELF-LOCKED VNODES 87 * 88 * ON EXIT: 89 * error: nothing held, etc. exec header still allocated. 90 * ok: filled exec package, one locked vnode. 91 * 92 * EXEC SWITCH ENTRY: 93 * Locked vnode to check, exec package, proc. 94 * 95 * EXEC SWITCH EXIT: 96 * ok: return 0, filled exec package, one locked vnode. 97 * error: destructive: 98 * everything deallocated execept exec header. 99 * non-descructive: 100 * error code, locked vnode, exec header unmodified 101 */ 102 int 103 check_exec(p, epp) 104 struct proc *p; 105 struct exec_package *epp; 106 { 107 int error, i; 108 struct vnode *vp; 109 struct nameidata *ndp; 110 size_t resid; 111 112 ndp = epp->ep_ndp; 113 ndp->ni_cnd.cn_nameiop = LOOKUP; 114 ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME; 115 /* first get the vnode */ 116 if ((error = namei(ndp)) != 0) 117 return (error); 118 epp->ep_vp = vp = ndp->ni_vp; 119 120 /* check for regular file */ 121 if (vp->v_type == VDIR) { 122 error = EISDIR; 123 goto bad1; 124 } 125 if (vp->v_type != VREG) { 126 error = EACCES; 127 goto bad1; 128 } 129 130 /* get attributes */ 131 if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0) 132 goto bad1; 133 134 /* Check mount point */ 135 if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 136 error = EACCES; 137 goto bad1; 138 } 139 140 if ((vp->v_mount->mnt_flag & MNT_NOSUID)) 141 epp->ep_vap->va_mode &= ~(VSUID | VSGID); 142 143 /* check access. for root we have to see if any exec bit on */ 144 if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0) 145 goto bad1; 146 if ((epp->ep_vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) { 147 error = EACCES; 148 goto bad1; 149 } 150 151 /* try to open it */ 152 if ((error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) != 0) 153 goto bad1; 154 155 /* now we have the file, get the exec header */ 156 error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0, 157 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); 158 if (error) 159 goto bad2; 160 epp->ep_hdrvalid = epp->ep_hdrlen - resid; 161 162 /* 163 * set up the vmcmds for creation of the process 164 * address space 165 */ 166 error = ENOEXEC; 167 for (i = 0; i < nexecs && error != 0; i++) { 168 int newerror; 169 170 if (execsw[i].es_check == NULL) 171 continue; 172 173 newerror = (*execsw[i].es_check)(p, epp); 174 /* make sure the first "interesting" error code is saved. */ 175 if (!newerror || error == ENOEXEC) 176 error = newerror; 177 if (epp->ep_flags & EXEC_DESTR && error != 0) 178 return (error); 179 } 180 if (!error) { 181 /* check that entry point is sane */ 182 if (epp->ep_entry > VM_MAXUSER_ADDRESS) { 183 error = ENOEXEC; 184 } 185 186 /* check limits */ 187 if ((epp->ep_tsize > MAXTSIZ) || 188 (epp->ep_dsize > p->p_rlimit[RLIMIT_DATA].rlim_cur)) 189 error = ENOMEM; 190 191 if (!error) 192 return (0); 193 } 194 195 /* 196 * free any vmspace-creation commands, 197 * and release their references 198 */ 199 kill_vmcmds(&epp->ep_vmcmds); 200 201 bad2: 202 /* 203 * unlock and close the vnode, free the 204 * pathname buf, and punt. 205 */ 206 VOP_UNLOCK(vp, 0, p); 207 vn_close(vp, FREAD, p->p_ucred, p); 208 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); 209 return (error); 210 211 bad1: 212 /* 213 * free the namei pathname buffer, and put the vnode 214 * (which we don't yet have open). 215 */ 216 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); 217 vput(vp); 218 return (error); 219 } 220 221 /* 222 * exec system call 223 */ 224 /* ARGSUSED */ 225 int 226 sys_execve(p, v, retval) 227 register struct proc *p; 228 void *v; 229 register_t *retval; 230 { 231 struct sys_execve_args /* { 232 syscallarg(char *) path; 233 syscallarg(char * *) argp; 234 syscallarg(char * *) envp; 235 } */ *uap = v; 236 int error, i; 237 struct exec_package pack; 238 struct nameidata nid; 239 struct vattr attr; 240 struct ucred *cred = p->p_ucred; 241 char *argp; 242 char * const *cpp, *dp, *sp; 243 long argc, envc; 244 size_t len, sgap; 245 #ifdef MACHINE_STACK_GROWS_UP 246 size_t slen; 247 #endif 248 char *stack; 249 struct ps_strings arginfo; 250 struct vmspace *vm = p->p_vmspace; 251 char **tmpfap; 252 int szsigcode; 253 extern struct emul emul_native; 254 255 /* 256 * figure out the maximum size of an exec header, if necessary. 257 * XXX should be able to keep LKM code from modifying exec switch 258 * when we're still using it, but... 259 */ 260 if (exec_maxhdrsz == 0) { 261 for (i = 0; i < nexecs; i++) 262 if (execsw[i].es_check != NULL 263 && execsw[i].es_hdrsz > exec_maxhdrsz) 264 exec_maxhdrsz = execsw[i].es_hdrsz; 265 } 266 267 /* init the namei data to point the file user's program name */ 268 NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 269 270 /* 271 * initialize the fields of the exec package. 272 */ 273 pack.ep_name = (char *)SCARG(uap, path); 274 pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK); 275 pack.ep_hdrlen = exec_maxhdrsz; 276 pack.ep_hdrvalid = 0; 277 pack.ep_ndp = &nid; 278 pack.ep_emul_arg = NULL; 279 VMCMDSET_INIT(&pack.ep_vmcmds); 280 pack.ep_vap = &attr; 281 pack.ep_emul = &emul_native; 282 pack.ep_flags = 0; 283 284 /* see if we can run it. */ 285 if ((error = check_exec(p, &pack)) != 0) { 286 goto freehdr; 287 } 288 289 /* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */ 290 291 /* allocate an argument buffer */ 292 argp = (char *) uvm_km_valloc_wait(exec_map, NCARGS); 293 #ifdef DIAGNOSTIC 294 if (argp == (vaddr_t) 0) 295 panic("execve: argp == NULL"); 296 #endif 297 dp = argp; 298 argc = 0; 299 300 /* copy the fake args list, if there's one, freeing it as we go */ 301 if (pack.ep_flags & EXEC_HASARGL) { 302 tmpfap = pack.ep_fa; 303 while (*tmpfap != NULL) { 304 char *cp; 305 306 cp = *tmpfap; 307 while (*cp) 308 *dp++ = *cp++; 309 dp++; 310 311 free(*tmpfap, M_EXEC); 312 tmpfap++; argc++; 313 } 314 FREE(pack.ep_fa, M_EXEC); 315 pack.ep_flags &= ~EXEC_HASARGL; 316 } 317 318 /* Now get argv & environment */ 319 if (!(cpp = SCARG(uap, argp))) { 320 error = EINVAL; 321 goto bad; 322 } 323 324 if (pack.ep_flags & EXEC_SKIPARG) 325 cpp++; 326 327 while (1) { 328 len = argp + ARG_MAX - dp; 329 if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) 330 goto bad; 331 if (!sp) 332 break; 333 if ((error = copyinstr(sp, dp, len, &len)) != 0) { 334 if (error == ENAMETOOLONG) 335 error = E2BIG; 336 goto bad; 337 } 338 dp += len; 339 cpp++; 340 argc++; 341 } 342 343 envc = 0; 344 /* environment need not be there */ 345 if ((cpp = SCARG(uap, envp)) != NULL ) { 346 while (1) { 347 len = argp + ARG_MAX - dp; 348 if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) 349 goto bad; 350 if (!sp) 351 break; 352 if ((error = copyinstr(sp, dp, len, &len)) != 0) { 353 if (error == ENAMETOOLONG) 354 error = E2BIG; 355 goto bad; 356 } 357 dp += len; 358 cpp++; 359 envc++; 360 } 361 } 362 363 dp = (char *)ALIGN(dp); 364 365 szsigcode = pack.ep_emul->e_esigcode - pack.ep_emul->e_sigcode; 366 367 sgap = STACKGAPLEN; 368 if (stackgap_random != 0) 369 sgap += (arc4random() * ALIGNBYTES) & (stackgap_random - 1); 370 /* Now check if args & environ fit into new stack */ 371 len = ((argc + envc + 2 + pack.ep_emul->e_arglen) * sizeof(char *) + 372 sizeof(long) + dp + sgap + szsigcode + 373 sizeof(struct ps_strings)) - argp; 374 375 len = ALIGN(len); /* make the stack "safely" aligned */ 376 377 if (len > pack.ep_ssize) { /* in effect, compare to initial limit */ 378 error = ENOMEM; 379 goto bad; 380 } 381 382 /* adjust "active stack depth" for process VSZ */ 383 pack.ep_ssize = len; /* maybe should go elsewhere, but... */ 384 385 /* 386 * Prepare vmspace for remapping. Note that uvmspace_exec can replace 387 * p_vmspace! 388 */ 389 uvmspace_exec(p); 390 391 vm = p->p_vmspace; 392 /* Now map address space */ 393 vm->vm_taddr = (char *)pack.ep_taddr; 394 vm->vm_tsize = btoc(pack.ep_tsize); 395 vm->vm_daddr = (char *)pack.ep_daddr; 396 vm->vm_dsize = btoc(pack.ep_dsize); 397 vm->vm_ssize = btoc(pack.ep_ssize); 398 vm->vm_maxsaddr = (char *)pack.ep_maxsaddr; 399 400 /* create the new process's VM space by running the vmcmds */ 401 #ifdef DIAGNOSTIC 402 if (pack.ep_vmcmds.evs_used == 0) 403 panic("execve: no vmcmds"); 404 #endif 405 for (i = 0; i < pack.ep_vmcmds.evs_used && !error; i++) { 406 struct exec_vmcmd *vcp; 407 408 vcp = &pack.ep_vmcmds.evs_cmds[i]; 409 error = (*vcp->ev_proc)(p, vcp); 410 } 411 412 /* free the vmspace-creation commands, and release their references */ 413 kill_vmcmds(&pack.ep_vmcmds); 414 415 /* if an error happened, deallocate and punt */ 416 if (error) 417 goto exec_abort; 418 419 /* remember information about the process */ 420 arginfo.ps_nargvstr = argc; 421 arginfo.ps_nenvstr = envc; 422 423 #ifdef MACHINE_STACK_GROWS_UP 424 stack = (char *)USRSTACK + sizeof(arginfo) + szsigcode; 425 slen = len - sizeof(arginfo) - szsigcode; 426 #else 427 stack = (char *)(USRSTACK - len); 428 #endif 429 /* Now copy argc, args & environ to new stack */ 430 if (!(*pack.ep_emul->e_copyargs)(&pack, &arginfo, stack, argp)) 431 goto exec_abort; 432 433 /* copy out the process's ps_strings structure */ 434 if (copyout(&arginfo, (char *)PS_STRINGS, sizeof(arginfo))) 435 goto exec_abort; 436 437 /* copy out the process's signal trampoline code */ 438 #ifdef MACHINE_STACK_GROWS_UP 439 if (szsigcode && copyout((char *)pack.ep_emul->e_sigcode, 440 ((char *)PS_STRINGS) + sizeof(arginfo), szsigcode)) 441 goto exec_abort; 442 #else 443 if (szsigcode && copyout((char *)pack.ep_emul->e_sigcode, 444 ((char *)PS_STRINGS) - szsigcode, szsigcode)) 445 goto exec_abort; 446 #endif 447 448 stopprofclock(p); /* stop profiling */ 449 fdcloseexec(p); /* handle close on exec */ 450 execsigs(p); /* reset catched signals */ 451 452 /* set command name & other accounting info */ 453 len = min(nid.ni_cnd.cn_namelen, MAXCOMLEN); 454 bcopy(nid.ni_cnd.cn_nameptr, p->p_comm, len); 455 p->p_comm[len] = 0; 456 p->p_acflag &= ~AFORK; 457 458 /* record proc's vnode, for use by procfs and others */ 459 if (p->p_textvp) 460 vrele(p->p_textvp); 461 VREF(pack.ep_vp); 462 p->p_textvp = pack.ep_vp; 463 464 p->p_flag |= P_EXEC; 465 if (p->p_flag & P_PPWAIT) { 466 p->p_flag &= ~P_PPWAIT; 467 wakeup((caddr_t)p->p_pptr); 468 } 469 470 /* 471 * If process does execve() while it has euid/uid or egid/gid 472 * which are mismatched, it remains P_SUGIDEXEC. 473 */ 474 if (p->p_ucred->cr_uid == p->p_cred->p_ruid && 475 p->p_ucred->cr_gid == p->p_cred->p_rgid) 476 p->p_flag &= ~P_SUGIDEXEC; 477 478 /* 479 * deal with set[ug]id. 480 * MNT_NOEXEC has already been used to disable s[ug]id. 481 */ 482 if ((attr.va_mode & (VSUID | VSGID)) && proc_cansugid(p)) { 483 int i; 484 485 p->p_flag |= P_SUGID; 486 p->p_flag |= P_SUGIDEXEC; 487 488 #ifdef KTRACE 489 /* 490 * If process is being ktraced, turn off - unless 491 * root set it. 492 */ 493 if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) { 494 p->p_traceflag = 0; 495 ktrsettracevnode(p, NULL); 496 } 497 #endif 498 p->p_ucred = crcopy(cred); 499 if (attr.va_mode & VSUID) 500 p->p_ucred->cr_uid = attr.va_uid; 501 if (attr.va_mode & VSGID) 502 p->p_ucred->cr_gid = attr.va_gid; 503 504 /* 505 * For set[ug]id processes, a few caveats apply to 506 * stdin, stdout, and stderr. 507 */ 508 for (i = 0; i < 3; i++) { 509 struct file *fp = NULL; 510 511 if (i < p->p_fd->fd_nfiles) 512 fp = p->p_fd->fd_ofiles[i]; 513 514 #ifdef PROCFS 515 /* 516 * Close descriptors that are writing to procfs. 517 */ 518 if (fp && fp->f_type == DTYPE_VNODE && 519 ((struct vnode *)(fp->f_data))->v_tag == VT_PROCFS && 520 (fp->f_flag & FWRITE)) { 521 fdrelease(p, i); 522 fp = NULL; 523 } 524 #endif 525 526 /* 527 * Ensure that stdin, stdout, and stderr are already 528 * allocated. We do not want userland to accidentally 529 * allocate descriptors in this range which has implied 530 * meaning to libc. 531 * 532 * XXX - Shouldn't the exec fail if we can't allocate 533 * resources here? 534 */ 535 if (fp == NULL) { 536 short flags = FREAD | (i == 0 ? 0 : FWRITE); 537 struct vnode *vp; 538 int indx; 539 540 if ((error = falloc(p, &fp, &indx)) != 0) 541 break; 542 #ifdef DIAGNOSTIC 543 if (indx != i) 544 panic("sys_execve: falloc indx != i"); 545 #endif 546 if ((error = cdevvp(getnulldev(), &vp)) != 0) { 547 ffree(fp); 548 fdremove(p->p_fd, indx); 549 break; 550 } 551 if ((error = VOP_OPEN(vp, flags, p->p_ucred, p)) != 0) { 552 ffree(fp); 553 fdremove(p->p_fd, indx); 554 vrele(vp); 555 break; 556 } 557 if (flags & FWRITE) 558 vp->v_writecount++; 559 fp->f_flag = flags; 560 fp->f_type = DTYPE_VNODE; 561 fp->f_ops = &vnops; 562 fp->f_data = (caddr_t)vp; 563 } 564 } 565 } else 566 p->p_flag &= ~P_SUGID; 567 p->p_cred->p_svuid = p->p_ucred->cr_uid; 568 p->p_cred->p_svgid = p->p_ucred->cr_gid; 569 570 if (p->p_flag & P_SUGIDEXEC) { 571 int i, s = splclock(); 572 573 timeout_del(&p->p_realit_to); 574 timerclear(&p->p_realtimer.it_interval); 575 timerclear(&p->p_realtimer.it_value); 576 for (i = 0; i < sizeof(p->p_stats->p_timer) / 577 sizeof(p->p_stats->p_timer[0]); i++) { 578 timerclear(&p->p_stats->p_timer[i].it_interval); 579 timerclear(&p->p_stats->p_timer[i].it_value); 580 } 581 splx(s); 582 } 583 584 uvm_km_free_wakeup(exec_map, (vaddr_t) argp, NCARGS); 585 586 FREE(nid.ni_cnd.cn_pnbuf, M_NAMEI); 587 VOP_CLOSE(pack.ep_vp, FREAD, cred, p); 588 vput(pack.ep_vp); 589 590 /* 591 * notify others that we exec'd 592 */ 593 KNOTE(&p->p_klist, NOTE_EXEC); 594 595 /* setup new registers and do misc. setup. */ 596 if (pack.ep_emul->e_fixup != NULL) { 597 if ((*pack.ep_emul->e_fixup)(p, &pack) != 0) 598 goto free_pack_abort; 599 } 600 #ifdef MACHINE_STACK_GROWS_UP 601 (*pack.ep_emul->e_setregs)(p, &pack, (u_long)stack + slen, retval); 602 #else 603 (*pack.ep_emul->e_setregs)(p, &pack, (u_long)stack, retval); 604 #endif 605 606 if (p->p_flag & P_TRACED) 607 psignal(p, SIGTRAP); 608 609 p->p_emul = pack.ep_emul; 610 free(pack.ep_hdr, M_EXEC); 611 612 #ifdef KTRACE 613 if (KTRPOINT(p, KTR_EMUL)) 614 ktremul(p, p->p_emul->e_name); 615 #endif 616 return (0); 617 618 bad: 619 /* free the vmspace-creation commands, and release their references */ 620 kill_vmcmds(&pack.ep_vmcmds); 621 /* kill any opened file descriptor, if necessary */ 622 if (pack.ep_flags & EXEC_HASFD) { 623 pack.ep_flags &= ~EXEC_HASFD; 624 (void) fdrelease(p, pack.ep_fd); 625 } 626 /* close and put the exec'd file */ 627 VOP_CLOSE(pack.ep_vp, FREAD, cred, p); 628 vput(pack.ep_vp); 629 FREE(nid.ni_cnd.cn_pnbuf, M_NAMEI); 630 uvm_km_free_wakeup(exec_map, (vaddr_t) argp, NCARGS); 631 632 freehdr: 633 free(pack.ep_hdr, M_EXEC); 634 return (error); 635 636 exec_abort: 637 /* 638 * the old process doesn't exist anymore. exit gracefully. 639 * get rid of the (new) address space we have created, if any, get rid 640 * of our namei data and vnode, and exit noting failure 641 */ 642 uvm_deallocate(&vm->vm_map, VM_MIN_ADDRESS, 643 VM_MAXUSER_ADDRESS - VM_MIN_ADDRESS); 644 if (pack.ep_emul_arg) 645 FREE(pack.ep_emul_arg, M_TEMP); 646 FREE(nid.ni_cnd.cn_pnbuf, M_NAMEI); 647 VOP_CLOSE(pack.ep_vp, FREAD, cred, p); 648 vput(pack.ep_vp); 649 uvm_km_free_wakeup(exec_map, (vaddr_t) argp, NCARGS); 650 651 free_pack_abort: 652 free(pack.ep_hdr, M_EXEC); 653 exit1(p, W_EXITCODE(0, SIGABRT)); 654 exit1(p, -1); 655 656 /* NOTREACHED */ 657 return (0); 658 } 659 660 661 void * 662 copyargs(pack, arginfo, stack, argp) 663 struct exec_package *pack; 664 struct ps_strings *arginfo; 665 void *stack; 666 void *argp; 667 { 668 char **cpp = stack; 669 char *dp, *sp; 670 size_t len; 671 void *nullp = NULL; 672 int argc = arginfo->ps_nargvstr; 673 int envc = arginfo->ps_nenvstr; 674 675 if (copyout(&argc, cpp++, sizeof(argc))) 676 return (NULL); 677 678 dp = (char *) (cpp + argc + envc + 2 + pack->ep_emul->e_arglen); 679 sp = argp; 680 681 /* XXX don't copy them out, remap them! */ 682 arginfo->ps_argvstr = cpp; /* remember location of argv for later */ 683 684 for (; --argc >= 0; sp += len, dp += len) 685 if (copyout(&dp, cpp++, sizeof(dp)) || 686 copyoutstr(sp, dp, ARG_MAX, &len)) 687 return (NULL); 688 689 if (copyout(&nullp, cpp++, sizeof(nullp))) 690 return (NULL); 691 692 arginfo->ps_envstr = cpp; /* remember location of envp for later */ 693 694 for (; --envc >= 0; sp += len, dp += len) 695 if (copyout(&dp, cpp++, sizeof(dp)) || 696 copyoutstr(sp, dp, ARG_MAX, &len)) 697 return (NULL); 698 699 if (copyout(&nullp, cpp++, sizeof(nullp))) 700 return (NULL); 701 702 return (cpp); 703 } 704