exec_elf.c revision 1.7 1 /* $NetBSD: exec_elf.c,v 1.7 1996/06/13 18:35:25 christos Exp $ */
2
3 /*
4 * Copyright (c) 1994 Christos Zoulas
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/proc.h>
35 #include <sys/malloc.h>
36 #include <sys/namei.h>
37 #include <sys/vnode.h>
38 #include <sys/exec.h>
39 #include <sys/exec_elf.h>
40
41 #include <sys/mman.h>
42 #include <vm/vm.h>
43 #include <vm/vm_param.h>
44 #include <vm/vm_map.h>
45
46 #include <machine/cpu.h>
47 #include <machine/reg.h>
48 #include <machine/exec.h>
49
50 #ifdef COMPAT_LINUX
51 #include <compat/linux/linux_exec.h>
52 #endif
53
54 #ifdef COMPAT_SVR4
55 #include <compat/svr4/svr4_exec.h>
56 #endif
57
58 int (*elf_probe_funcs[]) __P((struct proc *, struct exec_package *,
59 Elf32_Ehdr *, char *, u_long *)) = {
60 #ifdef COMPAT_LINUX
61 linux_elf_probe,
62 #endif
63 #ifdef COMPAT_SVR4
64 svr4_elf_probe,
65 #endif
66 };
67
68 int elf_check_header __P((Elf32_Ehdr *, int));
69 int elf_load_file __P((struct proc *, char *, struct exec_vmcmd_set *,
70 u_long *, struct elf_args *, u_long *));
71
72 static void elf_load_psection __P((struct exec_vmcmd_set *,
73 struct vnode *, Elf32_Phdr *, u_long *, u_long *, int *));
74
75 #define ELF_ALIGN(a, b) ((a) & ~((b) - 1))
76
77 /*
78 * Copy arguments onto the stack in the normal way, but add some
79 * extra information in case of dynamic binding.
80 */
81 void *
82 elf_copyargs(pack, arginfo, stack, argp)
83 struct exec_package *pack;
84 struct ps_strings *arginfo;
85 void *stack;
86 void *argp;
87 {
88 size_t len;
89 AuxInfo ai[ELF_AUX_ENTRIES], *a;
90 struct elf_args *ap;
91
92 stack = copyargs(pack, arginfo, stack, argp);
93 if (!stack)
94 return NULL;
95
96 /*
97 * Push extra arguments on the stack needed by dynamically
98 * linked binaries
99 */
100 if ((ap = (struct elf_args *) pack->ep_emul_arg)) {
101 a = ai;
102
103 a->au_id = AUX_phdr;
104 a->au_v = ap->arg_phaddr;
105 a++;
106
107 a->au_id = AUX_phent;
108 a->au_v = ap->arg_phentsize;
109 a++;
110
111 a->au_id = AUX_phnum;
112 a->au_v = ap->arg_phnum;
113 a++;
114
115 a->au_id = AUX_pagesz;
116 a->au_v = NBPG;
117 a++;
118
119 a->au_id = AUX_base;
120 a->au_v = ap->arg_interp;
121 a++;
122
123 a->au_id = AUX_flags;
124 a->au_v = 0;
125 a++;
126
127 a->au_id = AUX_entry;
128 a->au_v = ap->arg_entry;
129 a++;
130
131 a->au_id = AUX_null;
132 a->au_v = 0;
133 a++;
134
135 free((char *) ap, M_TEMP);
136 len = ELF_AUX_ENTRIES * sizeof (AuxInfo);
137 if (copyout(ai, stack, len))
138 return NULL;
139 stack += len;
140 }
141 return stack;
142 }
143
144 /*
145 * elf_check_header():
146 *
147 * Check header for validity; return 0 of ok ENOEXEC if error
148 *
149 * XXX machine type needs to be moved to <machine/param.h> so
150 * just one comparison can be done. Unfortunately, there is both
151 * em_486 and em_386, so this would not work on the i386.
152 */
153 int
154 elf_check_header(eh, type)
155 Elf32_Ehdr *eh;
156 int type;
157 {
158
159 if (bcmp(eh->e_ident, Elf32_e_ident, Elf32_e_siz) != 0)
160 return ENOEXEC;
161
162 switch (eh->e_machine) {
163 /* XXX */
164 #ifdef i386
165 case Elf32_em_386:
166 case Elf32_em_486:
167 #endif
168 #ifdef sparc
169 case Elf32_em_sparc:
170 #endif
171 break;
172
173 default:
174 return ENOEXEC;
175 }
176
177 if (eh->e_type != type)
178 return ENOEXEC;
179
180 return 0;
181 }
182
183 /*
184 * elf_load_psection():
185 *
186 * Load a psection at the appropriate address
187 */
188 static void
189 elf_load_psection(vcset, vp, ph, addr, size, prot)
190 struct exec_vmcmd_set *vcset;
191 struct vnode *vp;
192 Elf32_Phdr *ph;
193 u_long *addr;
194 u_long *size;
195 int *prot;
196 {
197 u_long uaddr, msize, rm, rf;
198 long diff, offset;
199
200 /*
201 * If the user specified an address, then we load there.
202 */
203 if (*addr != ELF32_NO_ADDR) {
204 if (ph->p_align > 1) {
205 *addr = ELF_ALIGN(*addr + ph->p_align, ph->p_align);
206 uaddr = ELF_ALIGN(ph->p_vaddr, ph->p_align);
207 } else
208 uaddr = ph->p_vaddr;
209 diff = ph->p_vaddr - uaddr;
210 } else {
211 *addr = uaddr = ph->p_vaddr;
212 if (ph->p_align > 1)
213 *addr = ELF_ALIGN(uaddr, ph->p_align);
214 diff = uaddr - *addr;
215 }
216
217 *prot |= (ph->p_flags & Elf32_pf_r) ? VM_PROT_READ : 0;
218 *prot |= (ph->p_flags & Elf32_pf_w) ? VM_PROT_WRITE : 0;
219 *prot |= (ph->p_flags & Elf32_pf_x) ? VM_PROT_EXECUTE : 0;
220
221 offset = ph->p_offset - diff;
222 *size = ph->p_filesz + diff;
223 msize = ph->p_memsz + diff;
224
225 NEW_VMCMD(vcset, vmcmd_map_readvn, *size, *addr, vp, offset, *prot);
226
227 /*
228 * Check if we need to extend the size of the segment
229 */
230 rm = round_page(*addr + msize);
231 rf = round_page(*addr + *size);
232
233 if (rm != rf) {
234 NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, *prot);
235 *size = msize;
236 }
237 }
238
239 /*
240 * elf_read_from():
241 *
242 * Read from vnode into buffer at offset.
243 */
244 int
245 elf_read_from(p, vp, off, buf, size)
246 struct vnode *vp;
247 u_long off;
248 struct proc *p;
249 caddr_t buf;
250 int size;
251 {
252 int error;
253 int resid;
254
255 if ((error = vn_rdwr(UIO_READ, vp, buf, size,
256 off, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
257 &resid, p)) != 0)
258 return error;
259 /*
260 * See if we got all of it
261 */
262 if (resid != 0)
263 return ENOEXEC;
264 return 0;
265 }
266
267 /*
268 * elf_load_file():
269 *
270 * Load a file (interpreter/library) pointed to by path
271 * [stolen from coff_load_shlib()]. Made slightly generic
272 * so it might be used externally.
273 */
274 int
275 elf_load_file(p, path, vcset, entry, ap, last)
276 struct proc *p;
277 char *path;
278 struct exec_vmcmd_set *vcset;
279 u_long *entry;
280 struct elf_args *ap;
281 u_long *last;
282 {
283 int error, i;
284 struct nameidata nd;
285 Elf32_Ehdr eh;
286 Elf32_Phdr *ph = NULL;
287 u_long phsize;
288 char *bp = NULL;
289 u_long addr = *last;
290
291 bp = path;
292 /*
293 * 1. open file
294 * 2. read filehdr
295 * 3. map text, data, and bss out of it using VM_*
296 */
297 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
298 if ((error = namei(&nd)) != 0) {
299 return error;
300 }
301 if ((error = elf_read_from(p, nd.ni_vp, 0, (caddr_t) &eh,
302 sizeof(eh))) != 0)
303 goto bad;
304
305 if ((error = elf_check_header(&eh, Elf32_et_dyn)) != 0)
306 goto bad;
307
308 phsize = eh.e_phnum * sizeof(Elf32_Phdr);
309 ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
310
311 if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff,
312 (caddr_t) ph, phsize)) != 0)
313 goto bad;
314
315 /*
316 * Load all the necessary sections
317 */
318 for (i = 0; i < eh.e_phnum; i++) {
319 u_long size = 0;
320 int prot = 0;
321
322 switch (ph[i].p_type) {
323 case Elf32_pt_load:
324 elf_load_psection(vcset, nd.ni_vp, &ph[i], &addr,
325 &size, &prot);
326 /* If entry is within this section it must be text */
327 if (eh.e_entry >= ph[i].p_vaddr &&
328 eh.e_entry < (ph[i].p_vaddr + size)) {
329 *entry = addr + eh.e_entry;
330 ap->arg_interp = addr;
331 }
332 addr += size;
333 break;
334
335 case Elf32_pt_dynamic:
336 case Elf32_pt_phdr:
337 case Elf32_pt_note:
338 break;
339
340 default:
341 break;
342 }
343 }
344
345 bad:
346 if (ph != NULL)
347 free((char *) ph, M_TEMP);
348
349 *last = addr;
350 vrele(nd.ni_vp);
351 return error;
352 }
353
354 /*
355 * exec_elf_makecmds(): Prepare an Elf binary's exec package
356 *
357 * First, set of the various offsets/lengths in the exec package.
358 *
359 * Then, mark the text image busy (so it can be demand paged) or error
360 * out if this is not possible. Finally, set up vmcmds for the
361 * text, data, bss, and stack segments.
362 *
363 * XXX no demand paging (yet?)
364 */
365 int
366 exec_elf_makecmds(p, epp)
367 struct proc *p;
368 struct exec_package *epp;
369 {
370 Elf32_Ehdr *eh = epp->ep_hdr;
371 Elf32_Phdr *ph, *pp;
372 Elf32_Addr phdr = 0;
373 int error, i, n, nload;
374 char interp[MAXPATHLEN];
375 u_long pos = 0, phsize;
376
377 if (epp->ep_hdrvalid < sizeof(Elf32_Ehdr))
378 return ENOEXEC;
379
380 if (elf_check_header(eh, Elf32_et_exec))
381 return ENOEXEC;
382
383 /*
384 * check if vnode is in open for writing, because we want to
385 * demand-page out of it. if it is, don't do it, for various
386 * reasons
387 */
388 if (epp->ep_vp->v_writecount != 0) {
389 #ifdef DIAGNOSTIC
390 if (epp->ep_vp->v_flag & VTEXT)
391 panic("exec: a VTEXT vnode has writecount != 0\n");
392 #endif
393 return ETXTBSY;
394 }
395 /*
396 * Allocate space to hold all the program headers, and read them
397 * from the file
398 */
399 phsize = eh->e_phnum * sizeof(Elf32_Phdr);
400 ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
401
402 if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff,
403 (caddr_t) ph, phsize)) != 0)
404 goto bad;
405
406 epp->ep_tsize = ELF32_NO_ADDR;
407 epp->ep_dsize = ELF32_NO_ADDR;
408
409 interp[0] = '\0';
410
411 for (i = 0; i < eh->e_phnum; i++) {
412 pp = &ph[i];
413 if (pp->p_type == Elf32_pt_interp) {
414 if (pp->p_filesz >= sizeof(interp))
415 goto bad;
416 if ((error = elf_read_from(p, epp->ep_vp, pp->p_offset,
417 (caddr_t) interp, pp->p_filesz)) != 0)
418 goto bad;
419 break;
420 }
421 }
422
423 /*
424 * On the same architecture, we may be emulating different systems.
425 * See which one will accept this executable. This currently only
426 * applies to Linux and SVR4 on the i386.
427 *
428 * Probe functions would normally see if the interpreter (if any)
429 * exists. Emulation packages may possibly replace the interpreter in
430 * interp[] with a changed path (/emul/xxx/<path>), and also
431 * set the ep_emul field in the exec package structure.
432 */
433 if ((n = sizeof elf_probe_funcs / sizeof elf_probe_funcs[0])) {
434 error = ENOEXEC;
435 for (i = 0; i < n && error; i++)
436 error = elf_probe_funcs[i](p, epp, eh, interp, &pos);
437
438 if (error)
439 goto bad;
440 }
441
442 /*
443 * Load all the necessary sections
444 */
445 for (i = nload = 0; i < eh->e_phnum; i++) {
446 u_long addr = ELF32_NO_ADDR, size = 0;
447 int prot = 0;
448
449 pp = &ph[i];
450
451 switch (ph[i].p_type) {
452 case Elf32_pt_load:
453 /*
454 * XXX
455 * Can handle only 2 sections: text and data
456 */
457 if (nload++ == 2)
458 goto bad;
459 elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
460 &ph[i], &addr, &size, &prot);
461 /*
462 * Decide whether it's text or data by looking
463 * at the entry point.
464 */
465 if (eh->e_entry >= addr && eh->e_entry < (addr + size)){
466 epp->ep_taddr = addr;
467 epp->ep_tsize = size;
468 } else {
469 epp->ep_daddr = addr;
470 epp->ep_dsize = size;
471 }
472 break;
473
474 case Elf32_pt_shlib:
475 error = ENOEXEC;
476 goto bad;
477
478 case Elf32_pt_interp:
479 /* Already did this one */
480 case Elf32_pt_dynamic:
481 case Elf32_pt_note:
482 break;
483
484 case Elf32_pt_phdr:
485 /* Note address of program headers (in text segment) */
486 phdr = pp->p_vaddr;
487 break;
488
489 default:
490 /*
491 * Not fatal, we don't need to understand everything
492 * :-)
493 */
494 break;
495 }
496 }
497
498 /*
499 * If no position to load the interpreter was set by a probe
500 * function, pick the same address that a non-fixed mmap(0, ..)
501 * would (i.e. something safely out of the way).
502 */
503 if (pos == ELF32_NO_ADDR)
504 pos = round_page(epp->ep_daddr + MAXDSIZ);
505
506 /*
507 * Check if we found a dynamically linked binary and arrange to load
508 * it's interpreter
509 */
510 if (interp[0]) {
511 struct elf_args *ap;
512
513 ap = (struct elf_args *) malloc(sizeof(struct elf_args),
514 M_TEMP, M_WAITOK);
515 if ((error = elf_load_file(p, interp, &epp->ep_vmcmds,
516 &epp->ep_entry, ap, &pos)) != 0) {
517 free((char *) ap, M_TEMP);
518 goto bad;
519 }
520 pos += phsize;
521 ap->arg_phaddr = phdr;
522
523 ap->arg_phentsize = eh->e_phentsize;
524 ap->arg_phnum = eh->e_phnum;
525 ap->arg_entry = eh->e_entry;
526
527 epp->ep_emul_arg = ap;
528 } else
529 epp->ep_entry = eh->e_entry;
530
531 free((char *) ph, M_TEMP);
532 epp->ep_vp->v_flag |= VTEXT;
533 return exec_aout_setup_stack(p, epp);
534
535 bad:
536 free((char *) ph, M_TEMP);
537 kill_vmcmds(&epp->ep_vmcmds);
538 return ENOEXEC;
539 }
540