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 without 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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD: releng/6.0/sys/alpha/linux/linux_sysvec.c 140992 2005-01-29 23:12:00Z sobomax $");
31
32 /* XXX we use functions that might not exist. */
33 #include "opt_compat.h"
34
35 #ifndef COMPAT_43
36 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
37 #endif
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/exec.h>
42 #include <sys/imgact.h>
43 #include <sys/imgact_aout.h>
44 #include <sys/imgact_elf.h>
45 #include <sys/kernel.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/module.h>
49 #include <sys/mutex.h>
50 #include <sys/proc.h>
51 #include <sys/signalvar.h>
52 #include <sys/sysent.h>
53
54 #include <vm/vm.h>
55 #include <vm/vm_param.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_extern.h>
58
59 #include <machine/cpu.h>
60 #include <machine/md_var.h>
61
62 #include <alpha/linux/linux.h>
63 #include <alpha/linux/linux_proto.h>
64 #include <compat/linux/linux_mib.h>
65 #include <compat/linux/linux_util.h>
66 #undef szsigcode
67
68 MODULE_VERSION(linux, 1);
69 MODULE_DEPEND(linux, osf1, 1, 1, 1);
70 MODULE_DEPEND(linux, sysvmsg, 1, 1, 1);
71 MODULE_DEPEND(linux, sysvsem, 1, 1, 1);
72 MODULE_DEPEND(linux, sysvshm, 1, 1, 1);
73
74 MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
75
76 #if BYTE_ORDER == LITTLE_ENDIAN
77 #define SHELLMAGIC 0x2123 /* #! */
78 #else
79 #define SHELLMAGIC 0x2321
80 #endif
81
82 SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
83
84 void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code);
85
86 static int elf_linux_fixup(register_t **stack_base,
87 struct image_params *iparams);
88 static int exec_linux_imgact_try(struct image_params *iparams);
89
90 static int
91 elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
92 {
93 Elf64_Auxargs *args;
94 register_t *pos;
95
96 KASSERT(curthread->td_proc == imgp->proc &&
97 (curthread->td_proc->p_flag & P_SA) == 0,
98 ("unsafe elf_linux_fixup(), should be curproc"));
99 args = (Elf64_Auxargs *)imgp->auxargs;
100 pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
101
102 if (args->trace)
103 AUXARGS_ENTRY(pos, AT_DEBUG, 1);
104 if (args->execfd != -1)
105 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
106 AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
107 AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
108 AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
109 AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
110 AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
111 AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
112 AUXARGS_ENTRY(pos, AT_BASE, args->base);
113 AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
114 AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
115 AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
116 AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
117 AUXARGS_ENTRY(pos, AT_NULL, 0);
118
119 free(imgp->auxargs, M_TEMP);
120 imgp->auxargs = NULL;
121
122 (*stack_base)--;
123 **stack_base = (register_t)imgp->args->argc;
124 return 0;
125 }
126
127 /*
128 * If a linux binary is exec'ing something, try this image activator
129 * first. We override standard shell script execution in order to
130 * be able to modify the interpreter path. We only do this if a linux
131 * binary is doing the exec, so we do not create an EXEC module for it.
132 */
133 static int
134 exec_linux_imgact_try(imgp)
135 struct image_params *imgp;
136 {
137 const char *head;
138 int error;
139
140 head = (const char *)imgp->image_header;
141 error = -1;
142
143 /*
144 * The interpreter for shell scripts run from a linux binary needs
145 * to be located in /compat/linux if possible in order to recursively
146 * maintain linux path emulation.
147 */
148 if (((const short *)head)[0] == SHELLMAGIC) {
149 /*
150 * Run our normal shell image activator. If it succeeds
151 * attempt to use the alternate path for the interpreter. If
152 * an alternate path is found, use our stringspace to store it.
153 */
154 if ((error = exec_shell_imgact(imgp)) == 0) {
155 char *rpath = NULL;
156
157 linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
158 imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0);
159 if (rpath != imgp->interpreter_name) {
160 int len = strlen(rpath) + 1;
161
162 if (len <= MAXSHELLCMDLEN) {
163 memcpy(imgp->interpreter_name, rpath,
164 len);
165 }
166 free(rpath, M_TEMP);
167 }
168 }
169 }
170 return(error);
171 }
172
173 /*
174 * To maintain OSF/1 compat, linux uses BSD signals & errnos on their
175 * alpha port. This greatly simplfies things for us.
176 */
177
178 struct sysentvec elf_linux_sysvec = {
179 LINUX_SYS_MAXSYSCALL,
180 linux_sysent,
181 0,
182 0,
183 NULL,
184 0,
185 NULL,
186 NULL,
187 elf_linux_fixup,
188 osendsig,
189 linux_sigcode,
190 &linux_szsigcode,
191 NULL,
192 "Linux ELF",
193 elf64_coredump,
194 exec_linux_imgact_try,
195 LINUX_MINSIGSTKSZ,
196 PAGE_SIZE,
197 VM_MIN_ADDRESS,
198 VM_MAXUSER_ADDRESS,
199 USRSTACK,
200 PS_STRINGS,
201 VM_PROT_ALL,
202 exec_copyout_strings,
203 exec_setregs,
204 NULL
205 };
206
207 static Elf64_Brandinfo linux_brand = {
208 ELFOSABI_LINUX,
209 EM_ALPHA,
210 "Linux",
211 "/compat/linux",
212 "/lib/ld-linux.so.1",
213 &elf_linux_sysvec,
214 NULL,
215 };
216
217 static Elf64_Brandinfo linux_glibc2brand = {
218 ELFOSABI_LINUX,
219 EM_ALPHA,
220 "Linux",
221 "/compat/linux",
222 "/lib/ld-linux.so.2",
223 &elf_linux_sysvec,
224 NULL,
225 };
226
227 Elf64_Brandinfo *linux_brandlist[] = {
228 &linux_brand,
229 &linux_glibc2brand,
230 NULL
231 };
232
233 static int
234 linux_elf_modevent(module_t mod, int type, void *data)
235 {
236 Elf64_Brandinfo **brandinfo;
237 int error;
238 struct linux_ioctl_handler **lihp;
239
240 error = 0;
241
242 switch(type) {
243 case MOD_LOAD:
244 for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
245 ++brandinfo)
246 if (elf64_insert_brand_entry(*brandinfo) < 0)
247 error = EINVAL;
248 if (error == 0) {
249 SET_FOREACH(lihp, linux_ioctl_handler_set)
250 linux_ioctl_register_handler(*lihp);
251 if (bootverbose)
252 printf("Linux ELF exec handler installed\n");
253 } else
254 printf("cannot insert Linux ELF brand handler\n");
255 break;
256 case MOD_UNLOAD:
257 for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
258 ++brandinfo)
259 if (elf64_brand_inuse(*brandinfo))
260 error = EBUSY;
261 if (error == 0) {
262 for (brandinfo = &linux_brandlist[0];
263 *brandinfo != NULL; ++brandinfo)
264 if (elf64_remove_brand_entry(*brandinfo) < 0)
265 error = EINVAL;
266 }
267 if (error == 0) {
268 SET_FOREACH(lihp, linux_ioctl_handler_set)
269 linux_ioctl_unregister_handler(*lihp);
270 if (bootverbose)
271 printf("Linux ELF exec handler removed\n");
272 linux_mib_destroy();
273 } else
274 printf("Could not deinstall ELF interpreter entry\n");
275 break;
276 default:
277 return (EOPNOTSUPP);
278 break;
279 }
280 return error;
281 }
282
283 static moduledata_t linux_elf_mod = {
284 "linuxelf",
285 linux_elf_modevent,
286 0
287 };
288
289 DUMMY(rt_sigreturn);
290
291 DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
Cache object: 9a9847818a79f9dfd565c6b490889c5c
|