Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / osf1 / osf1_exec_ecoff.c
blob721cdd1d83145670fd47851e8f8559b6a782543f
1 /* $NetBSD: osf1_exec_ecoff.c,v 1.20 2007/12/09 13:34:24 dogcow Exp $ */
3 /*
4 * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
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
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.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: osf1_exec_ecoff.c,v 1.20 2007/12/09 13:34:24 dogcow Exp $");
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>
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>
50 struct osf1_exec_emul_arg {
51 int flags;
52 #define OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER 0x01
54 char exec_name[MAXPATHLEN+1];
55 char loader_name[MAXPATHLEN+1];
58 static int osf1_exec_ecoff_dynamic(struct lwp *l, struct exec_package *epp);
60 int
61 osf1_exec_ecoff_probe(struct lwp *l, struct exec_package *epp)
63 struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
64 struct osf1_exec_emul_arg *emul_arg;
65 int error;
67 /* check if the binary is osf1 ecoff */
68 if (execp->f.f_magic != ECOFF_MAGIC_ALPHA)
69 return ENOEXEC;
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;
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
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;
97 case ECOFF_OBJECT_TYPE_CALL_SHARED:
98 error = osf1_exec_ecoff_dynamic(l, epp);
99 break;
101 default:
102 /* just let the normal ECOFF handlers deal with it. */
103 error = 0;
104 break;
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 */
113 return (error);
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.
121 osf1_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp)
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;
129 if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0)
130 goto out;
132 a = ai;
133 memset(ai, 0, sizeof ai);
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++;
144 * if there's a loader, push additional auxv entries on the stack.
146 if (emul_arg->flags & OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER) {
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++;
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++;
167 a->a_type = OSF1_AT_NULL;
168 a->a_un.a_val = 0;
169 a++;
171 len = (a - ai) * sizeof(struct osf1_auxv);
172 if ((error = copyout(ai, *stackp, len)) != 0)
173 goto out;
174 *stackp += len;
176 out:
177 free(pack->ep_emul_arg, M_TEMP);
178 pack->ep_emul_arg = NULL;
179 return error;
182 static int
183 osf1_exec_ecoff_dynamic(struct lwp *l, struct exec_package *epp)
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;
191 strncpy(emul_arg->loader_name, OSF1_LDR_EXEC_DEFAULT_LOADER,
192 MAXPATHLEN + 1);
195 * locate the loader
196 * includes /emul/osf1 if appropriate
198 error = emul_find_interp(LIST_FIRST(&l->l_proc->p_lwps),
199 epp, emul_arg->loader_name);
200 if (error)
201 return error;
203 emul_arg->flags |= OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER;
205 #if 0
206 uprintf("loader is %s\n", emul_arg->loader_name);
207 #endif
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.
214 ldr_vp = epp->ep_interp;
215 epp->ep_interp = NULL;
216 vn_lock(ldr_vp, LK_EXCLUSIVE | LK_RETRY);
219 * Basic access checks. Reject if:
220 * not a regular file
221 * exec not allowed on binary
222 * exec not allowed on mount point
224 if (ldr_vp->v_type != VREG) {
225 error = EACCES;
226 goto badunlock;
229 if ((error = VOP_ACCESS(ldr_vp, VEXEC, l->l_cred)) != 0)
230 goto badunlock;
232 if (ldr_vp->v_mount->mnt_flag & MNT_NOEXEC) {
233 error = EACCES;
234 goto badunlock;
238 * If loader's mount point disallows set-id execution,
239 * disable set-id.
241 if (ldr_vp->v_mount->mnt_flag & MNT_NOSUID)
242 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
244 VOP_UNLOCK(ldr_vp, 0);
247 * read the header, and make sure we got all of it.
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;
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.
263 if (ldr_exechdr.f.f_magic != ECOFF_MAGIC_ALPHA) {
264 error = ENOEXEC;
265 goto bad;
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;
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;
288 if (error)
289 goto bad;
291 /* finally, set up the stack. */
292 error = (*epp->ep_esch->es_setup_stack)(l, epp);
293 if (error)
294 goto bad;
296 vrele(ldr_vp);
297 return (0);
299 badunlock:
300 VOP_UNLOCK(ldr_vp, 0);
301 bad:
302 vrele(ldr_vp);
303 return (error);