Annotation of sys/compat/osf1/osf1_exec.c, Revision 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