1 /*-
2 * Copyright (c) 1994-1996 Søren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
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. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31 /* XXX we use functions that might not exist. */
32 #include "opt_compat.h"
33
34 #ifndef COMPAT_43
35 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
36 #endif
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/exec.h>
41 #include <sys/imgact.h>
42 #include <sys/imgact_aout.h>
43 #include <sys/imgact_elf.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/proc.h>
49 #include <sys/signalvar.h>
50 #include <sys/sysent.h>
51
52 #include <vm/vm.h>
53 #include <vm/vm_param.h>
54 #include <vm/vm_page.h>
55 #include <vm/vm_extern.h>
56
57 #include <machine/cpu.h>
58 #include <machine/md_var.h>
59
60 #include <alpha/linux/linux.h>
61 #include <alpha/linux/linux_proto.h>
62 #include <compat/linux/linux_util.h>
63 #undef szsigcode
64
65 MODULE_VERSION(linux, 1);
66 MODULE_DEPEND(linux, osf1, 1, 1, 1);
67 MODULE_DEPEND(linux, sysvmsg, 1, 1, 1);
68 MODULE_DEPEND(linux, sysvsem, 1, 1, 1);
69 MODULE_DEPEND(linux, sysvshm, 1, 1, 1);
70
71 MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
72
73 #if BYTE_ORDER == LITTLE_ENDIAN
74 #define SHELLMAGIC 0x2123 /* #! */
75 #else
76 #define SHELLMAGIC 0x2321
77 #endif
78
79 extern struct linker_set linux_ioctl_handler_set;
80 void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code);
81
82 static int elf_linux_fixup __P((long **stack_base,
83 struct image_params *iparams));
84 static int exec_linux_imgact_try __P((struct image_params *iparams));
85
86 static int
87 elf_linux_fixup(long **stack_base, struct image_params *imgp)
88 {
89 long *pos;
90 Elf64_Auxargs *args;
91
92 args = (Elf64_Auxargs *)imgp->auxargs;
93 pos = *stack_base + (imgp->argc + imgp->envc + 2);
94
95 if (args->trace) {
96 AUXARGS_ENTRY(pos, AT_DEBUG, 1);
97 }
98 if (args->execfd != -1) {
99 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
100 }
101 AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
102 AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
103 AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
104 AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
105 AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
106 AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
107 AUXARGS_ENTRY(pos, AT_BASE, args->base);
108 AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid);
109 AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid);
110 AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid);
111 AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid);
112 AUXARGS_ENTRY(pos, AT_NULL, 0);
113
114 free(imgp->auxargs, M_TEMP);
115 imgp->auxargs = NULL;
116
117 (*stack_base)--;
118 **stack_base = (long)imgp->argc;
119 return 0;
120 }
121
122 /*
123 * If a linux binary is exec'ing something, try this image activator
124 * first. We override standard shell script execution in order to
125 * be able to modify the interpreter path. We only do this if a linux
126 * binary is doing the exec, so we do not create an EXEC module for it.
127 */
128 static int
129 exec_linux_imgact_try(imgp)
130 struct image_params *imgp;
131 {
132 const char *head;
133 int error;
134
135 head = (const char *)imgp->image_header;
136 error = -1;
137
138 /*
139 * The interpreter for shell scripts run from a linux binary needs
140 * to be located in /compat/linux if possible in order to recursively
141 * maintain linux path emulation.
142 */
143 if (((const short *)head)[0] == SHELLMAGIC) {
144 /*
145 * Run our normal shell image activator. If it succeeds
146 * attempt to use the alternate path for the interpreter. If
147 * an alternate path is found, use our stringspace to store it.
148 */
149 if ((error = exec_shell_imgact(imgp)) == 0) {
150 char *rpath = NULL;
151
152 linux_emul_find(imgp->proc, NULL, linux_emul_path,
153 imgp->interpreter_name, &rpath, 0);
154 if (rpath != imgp->interpreter_name) {
155 int len = strlen(rpath) + 1;
156
157 if (len <= MAXSHELLCMDLEN) {
158 memcpy(imgp->interpreter_name, rpath,
159 len);
160 }
161 free(rpath, M_TEMP);
162 }
163 }
164 }
165 return(error);
166 }
167
168 /*
169 * To maintain OSF/1 compat, linux uses BSD signals & errnos on their
170 * alpha port. This greatly simplfies things for us.
171 */
172
173 struct sysentvec elf_linux_sysvec = {
174 LINUX_SYS_MAXSYSCALL,
175 linux_sysent,
176 0,
177 0,
178 0,
179 0,
180 0,
181 0,
182 elf_linux_fixup,
183 osendsig,
184 linux_sigcode,
185 &linux_szsigcode,
186 0,
187 "Linux ELF",
188 elf_coredump,
189 exec_linux_imgact_try,
190 LINUX_MINSIGSTKSZ
191 };
192
193 static Elf64_Brandinfo linux_brand = {
194 ELFOSABI_LINUX,
195 "Linux",
196 "/compat/linux",
197 "/lib/ld-linux.so.1",
198 &elf_linux_sysvec
199 };
200
201 static Elf64_Brandinfo linux_glibc2brand = {
202 ELFOSABI_LINUX,
203 "Linux",
204 "/compat/linux",
205 "/lib/ld-linux.so.2",
206 &elf_linux_sysvec
207 };
208
209 Elf64_Brandinfo *linux_brandlist[] = {
210 &linux_brand,
211 &linux_glibc2brand,
212 NULL
213 };
214
215 static int
216 linux_elf_modevent(module_t mod, int type, void *data)
217 {
218 Elf64_Brandinfo **brandinfo;
219 int error;
220
221 error = 0;
222
223 switch(type) {
224 case MOD_LOAD:
225 for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
226 ++brandinfo)
227 if (elf_insert_brand_entry(*brandinfo) < 0)
228 error = EINVAL;
229 if (error == 0) {
230 linux_ioctl_register_handlers(&linux_ioctl_handler_set);
231 if (bootverbose)
232 printf("Linux ELF exec handler installed\n");
233 } else
234 printf("cannot insert Linux ELF brand handler\n");
235 break;
236 case MOD_UNLOAD:
237 for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
238 ++brandinfo)
239 if (elf_brand_inuse(*brandinfo))
240 error = EBUSY;
241 if (error == 0) {
242 for (brandinfo = &linux_brandlist[0];
243 *brandinfo != NULL; ++brandinfo)
244 if (elf_remove_brand_entry(*brandinfo) < 0)
245 error = EINVAL;
246 }
247 if (error == 0) {
248 linux_ioctl_unregister_handlers(&linux_ioctl_handler_set);
249 if (bootverbose)
250 printf("Linux ELF exec handler removed\n");
251 } else
252 printf("Could not deinstall ELF interpreter entry\n");
253 break;
254 default:
255 break;
256 }
257 return error;
258 }
259
260 static moduledata_t linux_elf_mod = {
261 "linuxelf",
262 linux_elf_modevent,
263 0
264 };
265
266 DUMMY(rt_sigreturn);
267
268 DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
Cache object: a22332dd1f3f79356e4ae2d6a428355a
|