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

Annotation of sys/compat/osf1/osf1_exec.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: osf1_exec.c,v 1.5 2004/06/22 23:52:18 jfb Exp $ */
                      2: /* $NetBSD$ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *      This product includes software developed by Christopher G. Demetriou
                     18:  *     for the NetBSD Project.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/kernel.h>
                     37: #include <sys/proc.h>
                     38: #include <sys/malloc.h>
                     39: #include <sys/namei.h>
                     40: #include <sys/vnode.h>
                     41: #include <sys/mount.h>
                     42: #include <sys/exec.h>
                     43: #include <sys/exec_ecoff.h>
                     44: #include <sys/signalvar.h>
                     45: #include <sys/fcntl.h>
                     46: #include <sys/stat.h>
                     47:
                     48: #include <compat/osf1/osf1.h>
                     49: #include <compat/osf1/osf1_syscall.h>
                     50: #include <compat/osf1/osf1_util.h>
                     51: #include <compat/osf1/osf1_cvt.h>
                     52:
                     53: extern int scdebug;
                     54: extern char *osf1_syscallnames[];
                     55:
                     56:
                     57: struct osf1_exec_emul_arg {
                     58:         int        flags;
                     59: #define OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER        0x01
                     60:
                     61:         char        exec_name[MAXPATHLEN+1];
                     62:         char        loader_name[MAXPATHLEN+1];
                     63: };
                     64:
                     65: static void *osf1_copyargs(struct exec_package *pack,
                     66:        struct ps_strings *arginfo, void *stack, void *argp);
                     67: int osf1_exec_ecoff_hook(struct proc *, struct exec_package *);
                     68: static int osf1_exec_ecoff_dynamic(struct proc *, struct exec_package *);
                     69:
                     70: #define MAX_AUX_ENTRIES                4        /* max we'll ever push (right now) */
                     71:
                     72: extern struct sysent osf1_sysent[];
                     73: extern void cpu_exec_ecoff_setregs(struct proc *, struct exec_package *,
                     74:                                        u_long, register_t *);
                     75: extern char osf1_sigcode[], osf1_esigcode[];
                     76:
                     77: struct emul emul_osf1 = {
                     78:         "osf1",
                     79:         NULL,
                     80:         sendsig,
                     81:         OSF1_SYS_syscall,
                     82:         OSF1_SYS_MAXSYSCALL,
                     83:         osf1_sysent,
                     84: #ifdef SYSCALL_DEBUG
                     85:         osf1_syscallnames,
                     86: #else
                     87:         NULL,
                     88: #endif
                     89:         0,
                     90:         osf1_copyargs,
                     91:         cpu_exec_ecoff_setregs,
                     92:         NULL,
                     93:         osf1_sigcode,
                     94:         osf1_esigcode,
                     95: };
                     96:
                     97: int
                     98: osf1_exec_ecoff_hook(struct proc *p, struct exec_package *epp)
                     99: {
                    100:         struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
                    101:        struct osf1_exec_emul_arg *emul_arg;
                    102:        int error;
                    103:
                    104:        /* if we're here and we're exec-able at all, we're an OSF/1 binary */
                    105:        epp->ep_emul = &emul_osf1;
                    106:
                    107:        /* set up the exec package emul arg as appropriate */
                    108:        emul_arg = malloc(sizeof *emul_arg, M_TEMP, M_WAITOK);
                    109:        epp->ep_emul_arg = emul_arg;
                    110:
                    111:        emul_arg->flags = 0;
                    112:        if (epp->ep_ndp->ni_segflg == UIO_SYSSPACE)
                    113:                error = copystr(epp->ep_ndp->ni_dirp, emul_arg->exec_name,
                    114:                    MAXPATHLEN + 1, NULL);
                    115:        else
                    116:                error = copyinstr(epp->ep_ndp->ni_dirp, emul_arg->exec_name,
                    117:                    MAXPATHLEN + 1, NULL);
                    118: #ifdef DIAGNOSTIC
                    119:        if (error != 0)
                    120:                panic("osf1_exec_ecoff_hook: copyinstr failed");
                    121: #endif
                    122:
                    123:        /* do any special object file handling */
                    124:        switch (execp->f.f_flags & ECOFF_FLAG_OBJECT_TYPE_MASK) {
                    125:        case ECOFF_OBJECT_TYPE_SHARABLE:
                    126:                /* can't exec a shared library! */
                    127:                uprintf("can't execute OSF/1 shared libraries\n");
                    128:                error = ENOEXEC;
                    129:                break;
                    130:
                    131:        case ECOFF_OBJECT_TYPE_CALL_SHARED:
                    132:                error = osf1_exec_ecoff_dynamic(p, epp);
                    133:                break;
                    134:
                    135:        default:
                    136:                /* just let the normal ECOFF handlers deal with it. */
                    137:                error = 0;
                    138:                break;
                    139:        }
                    140:
                    141:        if (error) {
                    142:                free(epp->ep_emul_arg, M_TEMP);
                    143:                epp->ep_emul_arg = NULL;
                    144:                kill_vmcmds(&epp->ep_vmcmds);           /* if any */
                    145:        }
                    146:
                    147:        return (error);
                    148: }
                    149:
                    150: /*
                    151:  * copy arguments onto the stack in the normal way, then copy out
                    152:  * any ELF-like AUX entries used by the dynamic loading scheme.
                    153:  */
                    154: static void *
                    155: osf1_copyargs(pack, arginfo, stack, argp)
                    156:        struct exec_package *pack;
                    157:        struct ps_strings *arginfo;
                    158:        void *stack;
                    159:        void *argp;
                    160: {
                    161:        struct proc *p = curproc;                       /* XXX !!! */
                    162:        struct osf1_exec_emul_arg *emul_arg = pack->ep_emul_arg;
                    163:        struct osf1_auxv ai[MAX_AUX_ENTRIES], *a;
                    164:        char *prognameloc, *loadernameloc;
                    165:        size_t len;
                    166:
                    167:        stack = copyargs(pack, arginfo, stack, argp);
                    168:        if (!stack)
                    169:                goto bad;
                    170:
                    171:        a = ai;
                    172:        memset(ai, 0, sizeof ai);
                    173:
                    174:        prognameloc = (char *)stack + sizeof ai;
                    175:        if (copyoutstr(emul_arg->exec_name, prognameloc, MAXPATHLEN + 1, NULL))
                    176:            goto bad;
                    177:        a->a_type = OSF1_AT_EXEC_FILENAME;
                    178:        a->a_un.a_ptr = prognameloc;
                    179:        a++;
                    180:
                    181:        /*
                    182:         * if there's a loader, push additional auxv entries on the stack.
                    183:         */
                    184:        if (emul_arg->flags & OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER) {
                    185:
                    186:                loadernameloc = prognameloc + MAXPATHLEN + 1;
                    187:                if (copyoutstr(emul_arg->loader_name, loadernameloc,
                    188:                    MAXPATHLEN + 1, NULL))
                    189:                        goto bad;
                    190:                a->a_type = OSF1_AT_EXEC_LOADER_FILENAME;
                    191:                a->a_un.a_ptr = loadernameloc;
                    192:                a++;
                    193:
                    194:                a->a_type = OSF1_AT_EXEC_LOADER_FLAGS;
                    195:                a->a_un.a_val = 0;
                    196:                 if (pack->ep_vap->va_mode & S_ISUID)
                    197:                         a->a_un.a_val |= OSF1_LDR_EXEC_SETUID_F;
                    198:                 if (pack->ep_vap->va_mode & S_ISGID)
                    199:                         a->a_un.a_val |= OSF1_LDR_EXEC_SETGID_F;
                    200:                if (p->p_flag & P_TRACED)
                    201:                         a->a_un.a_val |= OSF1_LDR_EXEC_PTRACE_F;
                    202:                a++;
                    203:        }
                    204:
                    205:        a->a_type = OSF1_AT_NULL;
                    206:        a->a_un.a_val = 0;
                    207:        a++;
                    208:
                    209:        len = (a - ai) * sizeof(struct osf1_auxv);
                    210:        if (copyout(ai, stack, len))
                    211:                goto bad;
                    212:        stack = (caddr_t)stack + len;
                    213:
                    214: out:
                    215:        free(pack->ep_emul_arg, M_TEMP);
                    216:        pack->ep_emul_arg = NULL;
                    217:        return stack;
                    218:
                    219: bad:
                    220:        stack = NULL;
                    221:        goto out;
                    222: }
                    223:
                    224: static int
                    225: osf1_exec_ecoff_dynamic(struct proc *p, struct exec_package *epp)
                    226: {
                    227:        struct osf1_exec_emul_arg *emul_arg = epp->ep_emul_arg;
                    228:        struct ecoff_exechdr ldr_exechdr;
                    229:        struct nameidata nd;
                    230:        struct vnode *ldr_vp;
                    231:        char *pathbuf;
                    232:         size_t resid;
                    233:        int error;
                    234:
                    235:        /*
                    236:         * locate the loader
                    237:         */
                    238:        error = emul_find(p, NULL, osf1_emul_path,
                    239:            OSF1_LDR_EXEC_DEFAULT_LOADER, &pathbuf, 0);
                    240:        /* includes /emul/osf1 if appropriate */
                    241:        strlcpy(emul_arg->loader_name, pathbuf, sizeof(emul_arg->loader_name));
                    242:        emul_arg->flags |= OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER;
                    243:        if (!error)
                    244:                free((char *)pathbuf, M_TEMP);
                    245:
                    246:        uprintf("loader is %s\n", emul_arg->loader_name);
                    247:
                    248:        /*
                    249:         * open the loader, see if it's an ECOFF executable,
                    250:         * make sure the object type is amenable, then arrange to
                    251:         * load it up.
                    252:         */
                    253:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
                    254:            emul_arg->loader_name, p);
                    255:        if ((error = namei(&nd)) != 0)
                    256:                goto bad_no_vp;
                    257:        ldr_vp = nd.ni_vp;
                    258:
                    259:        /*
                    260:         * Basic access checks.  Reject if:
                    261:         *      not a regular file
                    262:         *      exec not allowed on binary
                    263:         *      exec not allowed on mount point
                    264:         */
                    265:        if (ldr_vp->v_type != VREG) {
                    266:                error = EACCES;
                    267:                goto badunlock;
                    268:        }
                    269:
                    270:        if ((error = VOP_ACCESS(ldr_vp, VEXEC, p->p_ucred, p)) != 0)
                    271:                goto badunlock;
                    272:
                    273:         if (ldr_vp->v_mount->mnt_flag & MNT_NOEXEC) {
                    274:                 error = EACCES;
                    275:                 goto badunlock;
                    276:         }
                    277:
                    278:        /*
                    279:         * If loader's mount point disallows set-id execution,
                    280:         * disable set-id.
                    281:         */
                    282:         if (ldr_vp->v_mount->mnt_flag & MNT_NOSUID)
                    283:                 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
                    284:
                    285:        VOP_UNLOCK(ldr_vp, 0, p);
                    286:
                    287:        /*
                    288:         * read the header, and make sure we got all of it.
                    289:         */
                    290:         if ((error = vn_rdwr(UIO_READ, ldr_vp, (caddr_t)&ldr_exechdr,
                    291:            sizeof ldr_exechdr, 0, UIO_SYSSPACE, 0, p->p_ucred,
                    292:            &resid, p)) != 0)
                    293:                 goto bad;
                    294:         if (resid != 0) {
                    295:                 error = ENOEXEC;
                    296:                 goto bad;
                    297:        }
                    298:
                    299:        /*
                    300:         * Check the magic.  We expect it to be the native Alpha ECOFF
                    301:         * (Digital UNIX) magic number.  Also make sure it's not a shared
                    302:         * lib or dynamically linked executable.
                    303:         */
                    304:        if (ldr_exechdr.f.f_magic != ECOFF_MAGIC_ALPHA) {
                    305:                error = ENOEXEC;
                    306:                goto bad;
                    307:        }
                    308:         switch (ldr_exechdr.f.f_flags & ECOFF_FLAG_OBJECT_TYPE_MASK) {
                    309:         case ECOFF_OBJECT_TYPE_SHARABLE:
                    310:         case ECOFF_OBJECT_TYPE_CALL_SHARED:
                    311:                /* can't exec shared lib or dynamically linked executable. */
                    312:                error = ENOEXEC;
                    313:                goto bad;
                    314:        }
                    315:
                    316:        switch (ldr_exechdr.a.magic) {
                    317:        case ECOFF_OMAGIC:
                    318:                error = exec_ecoff_prep_omagic(p, epp);
                    319:                break;
                    320:        case ECOFF_NMAGIC:
                    321:                error = exec_ecoff_prep_nmagic(p, epp);
                    322:                break;
                    323:        case ECOFF_ZMAGIC:
                    324:                error = exec_ecoff_prep_zmagic(p, epp);
                    325:                break;
                    326:        default:
                    327:                error = ENOEXEC;
                    328:        }
                    329:        if (error)
                    330:                goto bad;
                    331:
                    332:        vrele(ldr_vp);
                    333:        return (0);
                    334:
                    335: badunlock:
                    336:        VOP_UNLOCK(ldr_vp, 0, p);
                    337: bad:
                    338:        vrele(ldr_vp);
                    339: bad_no_vp:
                    340:        return (error);
                    341: }

CVSweb