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