linux_exec.c revision 1.29
1/* $NetBSD: linux_exec.c,v 1.29 1998/09/05 14:50:26 christos Exp $ */ 2 3/*- 4 * Copyright (c) 1994 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 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 the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * Copyright (c) 1995 Frank van der Linden 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. The name of the author may not be used to endorse or promote products 52 * derived from this software without specific prior written permission 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 57 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 58 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 60 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 61 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 62 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 63 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 * 65 * based on exec_aout.c, sunos_exec.c and svr4_exec.c 66 */ 67 68#define ELFSIZE 32 /* XXX should die */ 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/kernel.h> 73#include <sys/proc.h> 74#include <sys/malloc.h> 75#include <sys/namei.h> 76#include <sys/vnode.h> 77#include <sys/mount.h> 78#include <sys/exec.h> 79#include <sys/exec_elf.h> 80 81#include <sys/mman.h> 82#include <sys/syscallargs.h> 83 84#include <vm/vm.h> 85#include <vm/vm_param.h> 86#include <vm/vm_map.h> 87 88#include <machine/cpu.h> 89#include <machine/reg.h> 90#include <machine/linux_machdep.h> 91 92#include <compat/linux/linux_types.h> 93#include <compat/linux/linux_syscall.h> 94#include <compat/linux/linux_signal.h> 95#include <compat/linux/linux_syscallargs.h> 96#include <compat/linux/linux_util.h> 97#include <compat/linux/linux_exec.h> 98 99static void *linux_aout_copyargs __P((struct exec_package *, 100 struct ps_strings *, void *, void *)); 101static int linux_elf32_signature __P((struct proc *p, struct exec_package *, 102 Elf32_Ehdr *)); 103 104#define LINUX_AOUT_AUX_ARGSIZ 2 105#define LINUX_ELF_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *)) 106 107 108const char linux_emul_path[] = "/emul/linux"; 109extern int linux_error[]; 110extern char linux_sigcode[], linux_esigcode[]; 111extern struct sysent linux_sysent[]; 112extern char *linux_syscallnames[]; 113 114int exec_linux_aout_prep_zmagic __P((struct proc *, struct exec_package *)); 115int exec_linux_aout_prep_nmagic __P((struct proc *, struct exec_package *)); 116int exec_linux_aout_prep_omagic __P((struct proc *, struct exec_package *)); 117int exec_linux_aout_prep_qmagic __P((struct proc *, struct exec_package *)); 118 119struct emul emul_linux_aout = { 120 "linux", 121 linux_error, 122 linux_sendsig, 123 LINUX_SYS_syscall, 124 LINUX_SYS_MAXSYSCALL, 125 linux_sysent, 126 linux_syscallnames, 127 LINUX_AOUT_AUX_ARGSIZ, 128 linux_aout_copyargs, 129 linux_setregs, 130 linux_sigcode, 131 linux_esigcode, 132}; 133 134struct emul emul_linux_elf = { 135 "linux", 136 linux_error, 137 linux_sendsig, 138 LINUX_SYS_syscall, 139 LINUX_SYS_MAXSYSCALL, 140 linux_sysent, 141 linux_syscallnames, 142 LINUX_ELF_AUX_ARGSIZ, 143 elf32_copyargs, 144 linux_setregs, 145 linux_sigcode, 146 linux_esigcode, 147}; 148 149 150static void * 151linux_aout_copyargs(pack, arginfo, stack, argp) 152 struct exec_package *pack; 153 struct ps_strings *arginfo; 154 void *stack; 155 void *argp; 156{ 157 char **cpp = stack; 158 char **stk = stack; 159 char *dp, *sp; 160 size_t len; 161 void *nullp = NULL; 162 int argc = arginfo->ps_nargvstr; 163 int envc = arginfo->ps_nenvstr; 164 165 if (copyout(&argc, cpp++, sizeof(argc))) 166 return NULL; 167 168 /* leave room for envp and argv */ 169 cpp += 2; 170 if (copyout(&cpp, &stk[1], sizeof (cpp))) 171 return NULL; 172 173 dp = (char *) (cpp + argc + envc + 2); 174 sp = argp; 175 176 /* XXX don't copy them out, remap them! */ 177 arginfo->ps_argvstr = cpp; /* remember location of argv for later */ 178 179 for (; --argc >= 0; sp += len, dp += len) 180 if (copyout(&dp, cpp++, sizeof(dp)) || 181 copyoutstr(sp, dp, ARG_MAX, &len)) 182 return NULL; 183 184 if (copyout(&nullp, cpp++, sizeof(nullp))) 185 return NULL; 186 187 if (copyout(&cpp, &stk[2], sizeof (cpp))) 188 return NULL; 189 190 arginfo->ps_envstr = cpp; /* remember location of envp for later */ 191 192 for (; --envc >= 0; sp += len, dp += len) 193 if (copyout(&dp, cpp++, sizeof(dp)) || 194 copyoutstr(sp, dp, ARG_MAX, &len)) 195 return NULL; 196 197 if (copyout(&nullp, cpp++, sizeof(nullp))) 198 return NULL; 199 200 return cpp; 201} 202 203int 204exec_linux_aout_makecmds(p, epp) 205 struct proc *p; 206 struct exec_package *epp; 207{ 208 struct exec *linux_ep = epp->ep_hdr; 209 int machtype, magic; 210 int error = ENOEXEC; 211 212 magic = LINUX_N_MAGIC(linux_ep); 213 machtype = LINUX_N_MACHTYPE(linux_ep); 214 215 216 if (machtype != LINUX_MID_MACHINE) 217 return (ENOEXEC); 218 219 switch (magic) { 220 case QMAGIC: 221 error = exec_linux_aout_prep_qmagic(p, epp); 222 break; 223 case ZMAGIC: 224 error = exec_linux_aout_prep_zmagic(p, epp); 225 break; 226 case NMAGIC: 227 error = exec_linux_aout_prep_nmagic(p, epp); 228 break; 229 case OMAGIC: 230 error = exec_linux_aout_prep_omagic(p, epp); 231 break; 232 } 233 if (error == 0) 234 epp->ep_emul = &emul_linux_aout; 235 return error; 236} 237 238/* 239 * Since text starts at 0x400 in Linux ZMAGIC executables, and 0x400 240 * is very likely not page aligned on most architectures, it is treated 241 * as an NMAGIC here. XXX 242 */ 243 244int 245exec_linux_aout_prep_zmagic(p, epp) 246 struct proc *p; 247 struct exec_package *epp; 248{ 249 struct exec *execp = epp->ep_hdr; 250 251 epp->ep_taddr = LINUX_N_TXTADDR(*execp, ZMAGIC); 252 epp->ep_tsize = execp->a_text; 253 epp->ep_daddr = LINUX_N_DATADDR(*execp, ZMAGIC); 254 epp->ep_dsize = execp->a_data + execp->a_bss; 255 epp->ep_entry = execp->a_entry; 256 257 /* set up command for text segment */ 258 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text, 259 epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, ZMAGIC), 260 VM_PROT_READ|VM_PROT_EXECUTE); 261 262 /* set up command for data segment */ 263 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data, 264 epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, ZMAGIC), 265 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 266 267 /* set up command for bss segment */ 268 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss, 269 epp->ep_daddr + execp->a_data, NULLVP, 0, 270 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 271 272 return exec_aout_setup_stack(p, epp); 273} 274 275/* 276 * exec_aout_prep_nmagic(): Prepare Linux NMAGIC package. 277 * Not different from the normal stuff. 278 */ 279 280int 281exec_linux_aout_prep_nmagic(p, epp) 282 struct proc *p; 283 struct exec_package *epp; 284{ 285 struct exec *execp = epp->ep_hdr; 286 long bsize, baddr; 287 288 epp->ep_taddr = LINUX_N_TXTADDR(*execp, NMAGIC); 289 epp->ep_tsize = execp->a_text; 290 epp->ep_daddr = LINUX_N_DATADDR(*execp, NMAGIC); 291 epp->ep_dsize = execp->a_data + execp->a_bss; 292 epp->ep_entry = execp->a_entry; 293 294 /* set up command for text segment */ 295 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text, 296 epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, NMAGIC), 297 VM_PROT_READ|VM_PROT_EXECUTE); 298 299 /* set up command for data segment */ 300 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data, 301 epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, NMAGIC), 302 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 303 304 /* set up command for bss segment */ 305 baddr = roundup(epp->ep_daddr + execp->a_data, NBPG); 306 bsize = epp->ep_daddr + epp->ep_dsize - baddr; 307 if (bsize > 0) 308 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr, 309 NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 310 311 return exec_aout_setup_stack(p, epp); 312} 313 314/* 315 * exec_aout_prep_omagic(): Prepare Linux OMAGIC package. 316 * Business as usual. 317 */ 318 319int 320exec_linux_aout_prep_omagic(p, epp) 321 struct proc *p; 322 struct exec_package *epp; 323{ 324 struct exec *execp = epp->ep_hdr; 325 long dsize, bsize, baddr; 326 327 epp->ep_taddr = LINUX_N_TXTADDR(*execp, OMAGIC); 328 epp->ep_tsize = execp->a_text; 329 epp->ep_daddr = LINUX_N_DATADDR(*execp, OMAGIC); 330 epp->ep_dsize = execp->a_data + execp->a_bss; 331 epp->ep_entry = execp->a_entry; 332 333 /* set up command for text and data segments */ 334 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, 335 execp->a_text + execp->a_data, epp->ep_taddr, epp->ep_vp, 336 LINUX_N_TXTOFF(*execp, OMAGIC), VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 337 338 /* set up command for bss segment */ 339 baddr = roundup(epp->ep_daddr + execp->a_data, NBPG); 340 bsize = epp->ep_daddr + epp->ep_dsize - baddr; 341 if (bsize > 0) 342 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr, 343 NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 344 345 /* 346 * Make sure (# of pages) mapped above equals (vm_tsize + vm_dsize); 347 * obreak(2) relies on this fact. Both `vm_tsize' and `vm_dsize' are 348 * computed (in execve(2)) by rounding *up* `ep_tsize' and `ep_dsize' 349 * respectively to page boundaries. 350 * Compensate `ep_dsize' for the amount of data covered by the last 351 * text page. 352 */ 353 dsize = epp->ep_dsize + execp->a_text - roundup(execp->a_text, NBPG); 354 epp->ep_dsize = (dsize > 0) ? dsize : 0; 355 return exec_aout_setup_stack(p, epp); 356} 357 358int 359exec_linux_aout_prep_qmagic(p, epp) 360 struct proc *p; 361 struct exec_package *epp; 362{ 363 struct exec *execp = epp->ep_hdr; 364 365 epp->ep_taddr = LINUX_N_TXTADDR(*execp, QMAGIC); 366 epp->ep_tsize = execp->a_text; 367 epp->ep_daddr = LINUX_N_DATADDR(*execp, QMAGIC); 368 epp->ep_dsize = execp->a_data + execp->a_bss; 369 epp->ep_entry = execp->a_entry; 370 371 /* 372 * check if vnode is in open for writing, because we want to 373 * demand-page out of it. if it is, don't do it, for various 374 * reasons 375 */ 376 if ((execp->a_text != 0 || execp->a_data != 0) && 377 epp->ep_vp->v_writecount != 0) { 378#ifdef DIAGNOSTIC 379 if (epp->ep_vp->v_flag & VTEXT) 380 panic("exec: a VTEXT vnode has writecount != 0\n"); 381#endif 382 return ETXTBSY; 383 } 384 epp->ep_vp->v_flag |= VTEXT; 385 386 /* set up command for text segment */ 387 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text, 388 epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, QMAGIC), 389 VM_PROT_READ|VM_PROT_EXECUTE); 390 391 /* set up command for data segment */ 392 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data, 393 epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, QMAGIC), 394 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 395 396 /* set up command for bss segment */ 397 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss, 398 epp->ep_daddr + execp->a_data, NULLVP, 0, 399 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 400 401 return exec_aout_setup_stack(p, epp); 402} 403 404/* 405 * Take advantage of the fact that all the linux binaries are compiled 406 * with gcc, and gcc sticks in the comment field a signature. Note that 407 * on SVR4 binaries, the gcc signature will follow the OS name signature, 408 * that will not be a problem. We don't bother to read in the string table, 409 * but we check all the progbits headers. 410 */ 411static int 412linux_elf32_signature(p, epp, eh) 413 struct proc *p; 414 struct exec_package *epp; 415 Elf32_Ehdr *eh; 416{ 417 size_t shsize = sizeof(Elf32_Shdr) * eh->e_shnum; 418 size_t i; 419 static const char signature[] = "\0GCC: (GNU) "; 420 char buf[sizeof(signature) - 1]; 421 Elf32_Shdr *sh; 422 int error; 423 424 sh = (Elf32_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 425 426 if ((error = elf32_read_from(p, epp->ep_vp, eh->e_shoff, 427 (caddr_t) sh, shsize)) != 0) 428 goto out; 429 430 for (i = 0; i < eh->e_shnum; i++) { 431 Elf32_Shdr *s = &sh[i]; 432 433 /* 434 * Identify candidates for the comment header; 435 * Header cannot have a load address, or flags and 436 * it must be large enough. 437 */ 438 if (s->sh_type != Elf_sht_progbits || 439 s->sh_addr != 0 || 440 s->sh_flags != 0 || 441 s->sh_size < sizeof(signature) - 1) 442 continue; 443 444 if ((error = elf32_read_from(p, epp->ep_vp, s->sh_offset, 445 (caddr_t) buf, sizeof(signature) - 1)) != 0) 446 goto out; 447 448 /* 449 * error is 0, if the signatures match we are done. 450 */ 451 if (memcmp(buf, signature, sizeof(signature) - 1) == 0) 452 goto out; 453 } 454 error = EFTYPE; 455 456out: 457 free(sh, M_TEMP); 458 return error; 459} 460 461int 462linux_elf32_probe(p, epp, eh, itp, pos) 463 struct proc *p; 464 struct exec_package *epp; 465 Elf32_Ehdr *eh; 466 char *itp; 467 Elf32_Addr *pos; 468{ 469 char *bp; 470 int error; 471 size_t len; 472 473 if ((error = linux_elf32_signature(p, epp, eh)) != 0) 474 return error; 475 476 if (itp[0]) { 477 if ((error = emul_find(p, NULL, linux_emul_path, itp, &bp, 0))) 478 return error; 479 if ((error = copystr(bp, itp, MAXPATHLEN, &len))) 480 return error; 481 free(bp, M_TEMP); 482 } 483 epp->ep_emul = &emul_linux_elf; 484 *pos = ELF32_NO_ADDR; 485 return 0; 486} 487 488/* 489 * The Linux system call to load shared libraries, a.out version. The 490 * a.out shared libs are just files that are mapped onto a fixed 491 * address in the process' address space. The address is given in 492 * a_entry. Read in the header, set up some VM commands and run them. 493 * 494 * Yes, both text and data are mapped at once, so we're left with 495 * writeable text for the shared libs. The Linux crt0 seemed to break 496 * sometimes when data was mapped seperately. It munmapped a uselib() 497 * of ld.so by hand, which failed with shared text and data for ld.so 498 * Yuck. 499 * 500 * Because of the problem with ZMAGIC executables (text starts 501 * at 0x400 in the file, but needs to be mapped at 0), ZMAGIC 502 * shared libs are not handled very efficiently :-( 503 */ 504 505int 506linux_sys_uselib(p, v, retval) 507 struct proc *p; 508 void *v; 509 register_t *retval; 510{ 511 struct linux_sys_uselib_args /* { 512 syscallarg(char *) path; 513 } */ *uap = v; 514 caddr_t sg; 515 long bsize, dsize, tsize, taddr, baddr, daddr; 516 struct nameidata ni; 517 struct vnode *vp; 518 struct exec hdr; 519 struct exec_vmcmd_set vcset; 520 int i, magic, error; 521 size_t rem; 522 523 sg = stackgap_init(p->p_emul); 524 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 525 526 NDINIT(&ni, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 527 528 if ((error = namei(&ni))) 529 return error; 530 531 vp = ni.ni_vp; 532 533 if ((error = vn_rdwr(UIO_READ, vp, (caddr_t) &hdr, LINUX_AOUT_HDR_SIZE, 534 0, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, 535 &rem, p))) { 536 vrele(vp); 537 return error; 538 } 539 540 if (rem != 0) { 541 vrele(vp); 542 return ENOEXEC; 543 } 544 545 if (LINUX_N_MACHTYPE(&hdr) != LINUX_MID_MACHINE) 546 return ENOEXEC; 547 548 magic = LINUX_N_MAGIC(&hdr); 549 taddr = hdr.a_entry & (~(NBPG - 1)); 550 tsize = hdr.a_text; 551 daddr = taddr + tsize; 552 dsize = hdr.a_data + hdr.a_bss; 553 554 if ((hdr.a_text != 0 || hdr.a_data != 0) && vp->v_writecount != 0) { 555 vrele(vp); 556 return ETXTBSY; 557 } 558 vp->v_flag |= VTEXT; 559 560 vcset.evs_cnt = 0; 561 vcset.evs_used = 0; 562 563 NEW_VMCMD(&vcset, 564 magic == ZMAGIC ? vmcmd_map_readvn : vmcmd_map_pagedvn, 565 hdr.a_text + hdr.a_data, taddr, 566 vp, LINUX_N_TXTOFF(hdr, magic), 567 VM_PROT_READ|VM_PROT_EXECUTE|VM_PROT_WRITE); 568 569 baddr = roundup(daddr + hdr.a_data, NBPG); 570 bsize = daddr + dsize - baddr; 571 if (bsize > 0) { 572 NEW_VMCMD(&vcset, vmcmd_map_zero, bsize, baddr, 573 NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 574 } 575 576 for (i = 0; i < vcset.evs_used && !error; i++) { 577 struct exec_vmcmd *vcp; 578 579 vcp = &vcset.evs_cmds[i]; 580 error = (*vcp->ev_proc)(p, vcp); 581 } 582 583 kill_vmcmds(&vcset); 584 585 vrele(vp); 586 587 return error; 588} 589 590/* 591 * Execve(2). Just check the alternate emulation path, and pass it on 592 * to the NetBSD execve(). 593 */ 594int 595linux_sys_execve(p, v, retval) 596 struct proc *p; 597 void *v; 598 register_t *retval; 599{ 600 struct linux_sys_execve_args /* { 601 syscallarg(char *) path; 602 syscallarg(char **) argv; 603 syscallarg(char **) envp; 604 } */ *uap = v; 605 struct sys_execve_args ap; 606 caddr_t sg; 607 608 sg = stackgap_init(p->p_emul); 609 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 610 611 SCARG(&ap, path) = SCARG(uap, path); 612 SCARG(&ap, argp) = SCARG(uap, argp); 613 SCARG(&ap, envp) = SCARG(uap, envp); 614 615 return sys_execve(p, &ap, retval); 616} 617