root/compat/osf1/osf1_exec.c

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

DEFINITIONS

This source file includes following definitions.
  1. osf1_exec_ecoff_hook
  2. osf1_copyargs
  3. osf1_exec_ecoff_dynamic

    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 }

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