[BACK]Return to linux_exec.c CVS log [TXT][DIR] Up to [local] / sys / compat / linux

Annotation of sys/compat/linux/linux_exec.c, Revision 1.1

1.1     ! nbrk        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: }

CVSweb