1 /* $NetBSD: osf1_exec_ecoff.c,v 1.20 2007/12/09 13:34:24 dogcow Exp $ */
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
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>
39 #include <sys/malloc.h>
40 #include <sys/namei.h>
41 #include <sys/vnode.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
{
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
);
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
;
67 /* check if the binary is osf1 ecoff */
68 if (execp
->f
.f_magic
!= ECOFF_MAGIC_ALPHA
)
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
;
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
);
80 error
= copyinstr(epp
->ep_ndp
->ni_dirp
, emul_arg
->exec_name
,
81 MAXPATHLEN
+ 1, NULL
);
84 panic("osf1_exec_ecoff_probe: copyinstr failed");
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! */
92 uprintf("can't execute OSF/1 shared libraries\n");
97 case ECOFF_OBJECT_TYPE_CALL_SHARED
:
98 error
= osf1_exec_ecoff_dynamic(l
, epp
);
102 /* just let the normal ECOFF handlers deal with it. */
108 free(epp
->ep_emul_arg
, M_TEMP
);
109 epp
->ep_emul_arg
= NULL
;
110 kill_vmcmds(&epp
->ep_vmcmds
); /* if any */
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
;
129 if ((error
= copyargs(l
, pack
, arginfo
, stackp
, argp
)) != 0)
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)
139 a
->a_type
= OSF1_AT_EXEC_FILENAME
;
140 a
->a_un
.a_ptr
= prognameloc
;
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)
152 a
->a_type
= OSF1_AT_EXEC_LOADER_FILENAME
;
153 a
->a_un
.a_ptr
= loadernameloc
;
156 a
->a_type
= OSF1_AT_EXEC_LOADER_FLAGS
;
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
;
167 a
->a_type
= OSF1_AT_NULL
;
171 len
= (a
- ai
) * sizeof(struct osf1_auxv
);
172 if ((error
= copyout(ai
, *stackp
, len
)) != 0)
177 free(pack
->ep_emul_arg
, M_TEMP
);
178 pack
->ep_emul_arg
= NULL
;
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
;
191 strncpy(emul_arg
->loader_name
, OSF1_LDR_EXEC_DEFAULT_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
);
203 emul_arg
->flags
|= OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER
;
206 uprintf("loader is %s\n", emul_arg
->loader_name
);
210 * open the loader, see if it's an ECOFF executable,
211 * make sure the object type is amenable, then arrange to
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:
221 * exec not allowed on binary
222 * exec not allowed on mount point
224 if (ldr_vp
->v_type
!= VREG
) {
229 if ((error
= VOP_ACCESS(ldr_vp
, VEXEC
, l
->l_cred
)) != 0)
232 if (ldr_vp
->v_mount
->mnt_flag
& MNT_NOEXEC
) {
238 * If loader's mount point disallows set-id execution,
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
,
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
) {
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. */
275 switch (ldr_exechdr
.a
.magic
) {
277 error
= exec_ecoff_prep_omagic(l
, epp
, &ldr_exechdr
, ldr_vp
);
280 error
= exec_ecoff_prep_nmagic(l
, epp
, &ldr_exechdr
, ldr_vp
);
283 error
= exec_ecoff_prep_zmagic(l
, epp
, &ldr_exechdr
, ldr_vp
);
291 /* finally, set up the stack. */
292 error
= (*epp
->ep_esch
->es_setup_stack
)(l
, epp
);
300 VOP_UNLOCK(ldr_vp
, 0);