The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/osf1/osf1_exec_ecoff.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: efc109b84b3e11cf1f4147a6bd80d711


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.