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/5.2/sys/alpha/linux/linux_sysvec.c 120422 2003-09-25 01:10:26Z peter $");
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->argc + imgp->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->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_find(FIRST_THREAD_IN_PROC(imgp->proc), NULL,
158 imgp->interpreter_name, &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 };
215
216 static Elf64_Brandinfo linux_glibc2brand = {
217 ELFOSABI_LINUX,
218 EM_ALPHA,
219 "Linux",
220 "/compat/linux",
221 "/lib/ld-linux.so.2",
222 &elf_linux_sysvec
223 };
224
225 Elf64_Brandinfo *linux_brandlist[] = {
226 &linux_brand,
227 &linux_glibc2brand,
228 NULL
229 };
230
231 static int
232 linux_elf_modevent(module_t mod, int type, void *data)
233 {
234 Elf64_Brandinfo **brandinfo;
235 int error;
236 struct linux_ioctl_handler **lihp;
237
238 error = 0;
239
240 switch(type) {
241 case MOD_LOAD:
242 for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
243 ++brandinfo)
244 if (elf64_insert_brand_entry(*brandinfo) < 0)
245 error = EINVAL;
246 if (error == 0) {
247 SET_FOREACH(lihp, linux_ioctl_handler_set)
248 linux_ioctl_register_handler(*lihp);
249 if (bootverbose)
250 printf("Linux ELF exec handler installed\n");
251 } else
252 printf("cannot insert Linux ELF brand handler\n");
253 break;
254 case MOD_UNLOAD:
255 for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
256 ++brandinfo)
257 if (elf64_brand_inuse(*brandinfo))
258 error = EBUSY;
259 if (error == 0) {
260 for (brandinfo = &linux_brandlist[0];
261 *brandinfo != NULL; ++brandinfo)
262 if (elf64_remove_brand_entry(*brandinfo) < 0)
263 error = EINVAL;
264 }
265 if (error == 0) {
266 SET_FOREACH(lihp, linux_ioctl_handler_set)
267 linux_ioctl_unregister_handler(*lihp);
268 if (bootverbose)
269 printf("Linux ELF exec handler removed\n");
270 linux_mib_destroy();
271 } else
272 printf("Could not deinstall ELF interpreter entry\n");
273 break;
274 default:
275 break;
276 }
277 return error;
278 }
279
280 static moduledata_t linux_elf_mod = {
281 "linuxelf",
282 linux_elf_modevent,
283 0
284 };
285
286 DUMMY(rt_sigreturn);
287
288 DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
Cache object: b51de8c957a7b8239482d99bbdc81ce4
|