root/compat/linux/linux_exec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. linux_e_proc_init
  2. linux_e_proc_exec
  3. linux_e_proc_exit
  4. linux_e_proc_fork
  5. linux_aout_copyargs
  6. exec_linux_aout_makecmds
  7. exec_linux_aout_prep_zmagic
  8. exec_linux_aout_prep_nmagic
  9. exec_linux_aout_prep_omagic
  10. exec_linux_aout_prep_qmagic
  11. exec_linux_elf32_makecmds
  12. linux_elf_probe
  13. linux_sys_uselib
  14. linux_sys_execve

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

/* [<][>][^][v][top][bottom][index][help] */