exec_elf.c revision 1.1 1 /* $NetBSD: exec_elf.c,v 1.1 1995/06/22 21:29:53 fvdl 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[])() = {
59 #ifdef COMPAT_SVR4
60 svr4_elf_probe,
61 #endif
62 #ifdef COMPAT_LINUX
63 linux_elf_probe
64 #endif
65 };
66
67 static int elf_set_segment __P((struct exec_package *, u_long, u_long,
68 int));
69 static int elf_read_from __P((struct proc *, struct vnode *, u_long,
70 caddr_t, int));
71 static void elf_load_psection __P((struct exec_vmcmd_set *,
72 struct vnode *, Elf32_Phdr *, u_long *, u_long *, int *));
73
74 #define ELF_ALIGN(a, b) ((a) & ~((b) - 1))
75 #define ELF_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
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 char **cpp = stack;
89 char *dp, *sp;
90 size_t len;
91 void *nullp = NULL;
92 int argc = arginfo->ps_nargvstr;
93 int envc = arginfo->ps_nenvstr;
94 AuxInfo *a;
95 struct elf_args *ap;
96
97 if (copyout(&argc, cpp++, sizeof(argc)))
98 return NULL;
99
100 dp = (char *) (cpp + argc + envc + 2 + pack->ep_emul->e_arglen);
101 sp = argp;
102
103 /* XXX don't copy them out, remap them! */
104 arginfo->ps_argvstr = cpp; /* remember location of argv for later */
105
106 for (; --argc >= 0; sp += len, dp += len)
107 if (copyout(&dp, cpp++, sizeof(dp)) ||
108 copyoutstr(sp, dp, ARG_MAX, &len))
109 return NULL;
110
111 if (copyout(&nullp, cpp++, sizeof(nullp)))
112 return NULL;
113
114 arginfo->ps_envstr = cpp; /* remember location of envp for later */
115
116 for (; --envc >= 0; sp += len, dp += len)
117 if (copyout(&dp, cpp++, sizeof(dp)) ||
118 copyoutstr(sp, dp, ARG_MAX, &len))
119 return NULL;
120
121 if (copyout(&nullp, cpp++, sizeof(nullp)))
122 return NULL;
123
124 /*
125 * Push extra arguments on the stack needed by dynamically
126 * linked binaries
127 */
128 a = (AuxInfo *) cpp;
129 if ((ap = (struct elf_args *) pack->ep_emul_arg)) {
130
131 a->au_id = AUX_phdr;
132 a->au_v = ap->arg_phaddr;
133 a++;
134
135 a->au_id = AUX_phent;
136 a->au_v = ap->arg_phentsize;
137 a++;
138
139 a->au_id = AUX_phnum;
140 a->au_v = ap->arg_phnum;
141 a++;
142
143 a->au_id = AUX_pagesz;
144 a->au_v = NBPG;
145 a++;
146
147 a->au_id = AUX_base;
148 a->au_v = ap->arg_interp;
149 a++;
150
151 a->au_id = AUX_flags;
152 a->au_v = 0;
153 a++;
154
155 a->au_id = AUX_entry;
156 a->au_v = ap->arg_entry;
157 a++;
158
159 a->au_id = AUX_null;
160 a->au_v = 0;
161 a++;
162
163 free((char *) ap, M_TEMP);
164 }
165 return a;
166 }
167
168 /*
169 * elf_check_header():
170 *
171 * Check header for validity; return 0 of ok ENOEXEC if error
172 *
173 * XXX machine type needs to be moved to <machine/param.h> so
174 * just one comparison can be done. Unfortunately, there is both
175 * em_486 and em_386, so this would not work on the i386.
176 */
177 int
178 elf_check_header(eh, type)
179 Elf32_Ehdr *eh;
180 int type;
181 {
182 #ifdef sparc
183 /* #$%@#$%@#$%! */
184 # define memcmp bcmp
185 #endif
186 if (memcmp(eh->e_ident, Elf32_e_ident, Elf32_e_siz) != 0)
187 return ENOEXEC;
188
189 switch (eh->e_machine) {
190 /* XXX */
191 #ifdef i386
192 case Elf32_em_386:
193 case Elf32_em_486:
194 #endif
195 #ifdef sparc
196 case Elf32_em_sparc:
197 #endif
198 break;
199
200 default:
201 return ENOEXEC;
202 }
203
204 if (eh->e_type != type)
205 return ENOEXEC;
206
207 return 0;
208 }
209
210 /*
211 * elf_load_psection():
212 *
213 * Load a psection at the appropriate address
214 */
215 static void
216 elf_load_psection(vcset, vp, ph, addr, size, prot)
217 struct exec_vmcmd_set *vcset;
218 struct vnode *vp;
219 Elf32_Phdr *ph;
220 u_long *addr;
221 u_long *size;
222 int *prot;
223 {
224 u_long uaddr, msize, rm, rf;
225 long diff, offset;
226
227 /*
228 * If the user specified an address, then we load there.
229 */
230 if (*addr != ELF32_NO_ADDR) {
231 if (ph->p_align > 1) {
232 *addr = ELF_ALIGN(*addr + ph->p_align, ph->p_align);
233 uaddr = ELF_ALIGN(ph->p_vaddr, ph->p_align);
234 } else
235 uaddr = ph->p_vaddr;
236 diff = ph->p_vaddr - uaddr;
237 } else {
238 *addr = uaddr = ph->p_vaddr;
239 if (ph->p_align > 1)
240 *addr = ELF_ALIGN(uaddr, ph->p_align);
241 diff = uaddr - *addr;
242 }
243
244 *prot |= (ph->p_flags & Elf32_pf_r) ? VM_PROT_READ : 0;
245 *prot |= (ph->p_flags & Elf32_pf_w) ? VM_PROT_WRITE : 0;
246 *prot |= (ph->p_flags & Elf32_pf_x) ? VM_PROT_EXECUTE : 0;
247
248 offset = ph->p_offset - diff;
249 *size = ph->p_filesz + diff;
250 msize = ph->p_memsz + diff;
251
252 NEW_VMCMD(vcset, vmcmd_map_readvn, *size, *addr, vp, offset, *prot);
253
254 /*
255 * Check if we need to extend the size of the segment
256 */
257 rm = round_page(*addr + msize);
258 rf = round_page(*addr + *size);
259
260 if (rm != rf) {
261 NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, *prot);
262 *size = msize;
263 }
264 }
265
266 /*
267 * elf_set_segment():
268 *
269 * Decide if the segment is text or data, depending on the protection
270 * and set it appropriately
271 */
272 static int
273 elf_set_segment(epp, vaddr, size, prot)
274 struct exec_package *epp;
275 u_long vaddr;
276 u_long size;
277 int prot;
278 {
279 /*
280 * Kludge: Unfortunately the current implementation of
281 * exec package assumes a single text and data segment.
282 * In Elf we can have more, but here we limit ourselves
283 * to two and hope :-(
284 * We also assume that the text is r-x, and data is rwx or rw-.
285 */
286 switch (prot) {
287 case (VM_PROT_READ | VM_PROT_EXECUTE):
288 if (epp->ep_tsize != ELF32_NO_ADDR)
289 return ENOEXEC;
290 epp->ep_taddr = vaddr;
291 epp->ep_tsize = size;
292 break;
293
294 case (VM_PROT_READ | VM_PROT_WRITE):
295 case (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE):
296 if (epp->ep_dsize != ELF32_NO_ADDR)
297 return ENOEXEC;
298 epp->ep_daddr = vaddr;
299 epp->ep_dsize = size;
300 break;
301
302 default:
303 return ENOEXEC;
304 }
305 return 0;
306 }
307
308 /*
309 * elf_read_from():
310 *
311 * Read from vnode into buffer at offset.
312 */
313 static int
314 elf_read_from(p, vp, off, buf, size)
315 struct vnode *vp;
316 u_long off;
317 struct proc *p;
318 caddr_t buf;
319 int size;
320 {
321 int error;
322 int resid;
323
324 if ((error = vn_rdwr(UIO_READ, vp, buf, size,
325 off, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
326 &resid, p)) != 0)
327 return error;
328 /*
329 * See if we got all of it
330 */
331 if (resid != 0)
332 return error;
333 return 0;
334 }
335
336 /*
337 * elf_load_file():
338 *
339 * Load a file (interpreter/library) pointed to by path
340 * [stolen from coff_load_shlib()]. Made slightly generic
341 * so it might be used externally.
342 */
343 int
344 elf_load_file(p, path, vcset, entry, ap, last)
345 struct proc *p;
346 char *path;
347 struct exec_vmcmd_set *vcset;
348 u_long *entry;
349 struct elf_args *ap;
350 u_long *last;
351 {
352 int error, i;
353 struct nameidata nd;
354 Elf32_Ehdr eh;
355 Elf32_Phdr *ph = NULL;
356 u_long phsize;
357 char *bp = NULL;
358 u_long addr = *last;
359
360 bp = path;
361 /*
362 * 1. open file
363 * 2. read filehdr
364 * 3. map text, data, and bss out of it using VM_*
365 */
366 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
367 if ((error = namei(&nd)) != 0) {
368 return error;
369 }
370 if ((error = elf_read_from(p, nd.ni_vp, 0, (caddr_t) &eh,
371 sizeof(eh))) != 0)
372 goto bad;
373
374 if ((error = elf_check_header(&eh, Elf32_et_dyn)) != 0)
375 goto bad;
376
377 phsize = eh.e_phnum * sizeof(Elf32_Phdr);
378 ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
379
380 if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff,
381 (caddr_t) ph, phsize)) != 0)
382 goto bad;
383
384 /*
385 * Load all the necessary sections
386 */
387 for (i = 0; i < eh.e_phnum; i++) {
388 u_long size = 0;
389 int prot = 0;
390
391 switch (ph[i].p_type) {
392 case Elf32_pt_load:
393 elf_load_psection(vcset, nd.ni_vp, &ph[i], &addr,
394 &size, &prot);
395 /* Assume that the text segment is r-x only */
396 if ((prot & PROT_WRITE) == 0) {
397 *entry = addr + eh.e_entry;
398 ap->arg_interp = addr;
399 }
400 addr += size;
401 break;
402
403 case Elf32_pt_dynamic:
404 case Elf32_pt_phdr:
405 case Elf32_pt_note:
406 break;
407
408 default:
409 break;
410 }
411 }
412
413 bad:
414 if (ph != NULL)
415 free((char *) ph, M_TEMP);
416
417 *last = addr;
418 vrele(nd.ni_vp);
419 return error;
420 }
421
422 /*
423 * exec_elf_makecmds(): Prepare an Elf binary's exec package
424 *
425 * First, set of the various offsets/lengths in the exec package.
426 *
427 * Then, mark the text image busy (so it can be demand paged) or error
428 * out if this is not possible. Finally, set up vmcmds for the
429 * text, data, bss, and stack segments.
430 *
431 * XXX no demand paging (yet?)
432 */
433 int
434 exec_elf_makecmds(p, epp)
435 struct proc *p;
436 struct exec_package *epp;
437 {
438 Elf32_Ehdr *eh = epp->ep_hdr;
439 Elf32_Phdr *ph, *pp;
440 int error, i, n;
441 char interp[MAXPATHLEN];
442 u_long pos = 0, phsize;
443
444 if (epp->ep_hdrvalid < sizeof(Elf32_Ehdr))
445 return ENOEXEC;
446
447 if (elf_check_header(eh, Elf32_et_exec))
448 return ENOEXEC;
449
450 /*
451 * check if vnode is in open for writing, because we want to
452 * demand-page out of it. if it is, don't do it, for various
453 * reasons
454 */
455 if (epp->ep_vp->v_writecount != 0) {
456 #ifdef DIAGNOSTIC
457 if (epp->ep_vp->v_flag & VTEXT)
458 panic("exec: a VTEXT vnode has writecount != 0\n");
459 #endif
460 return ETXTBSY;
461 }
462 /*
463 * Allocate space to hold all the program headers, and read them
464 * from the file
465 */
466 phsize = eh->e_phnum * sizeof(Elf32_Phdr);
467 ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
468
469 if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff,
470 (caddr_t) ph, phsize)) != 0)
471 goto bad;
472
473 epp->ep_tsize = ELF32_NO_ADDR;
474 epp->ep_dsize = ELF32_NO_ADDR;
475
476 interp[0] = '\0';
477
478 for (i = 0; i < eh->e_phnum; i++) {
479 pp = &ph[i];
480 if (pp->p_type == Elf32_pt_interp) {
481 if (pp->p_filesz >= sizeof(interp))
482 goto bad;
483 if ((error = elf_read_from(p, epp->ep_vp, pp->p_offset,
484 (caddr_t) interp, pp->p_filesz)) != 0)
485 goto bad;
486 break;
487 }
488 }
489
490 /*
491 * On the same architecture, we may be emulating different systems.
492 * See which one will accept this executable. This currently only
493 * applies to Linux and SVR4 on the i386.
494 *
495 * Probe functions would normally see if the interpreter (if any)
496 * exists. Emulation packages may possibly replace the interpreter in
497 * interp[] with a changed path (/emul/xxx/<path>), and also
498 * set the ep_emul field in the exec package structure.
499 */
500 if ((n = sizeof elf_probe_funcs / sizeof elf_probe_funcs[0])) {
501 error = ENOEXEC;
502 for (i = 0; i < n && error; i++)
503 error = elf_probe_funcs[i](p, epp, interp, &pos);
504
505 if (error)
506 goto bad;
507 }
508
509 /*
510 * Load all the necessary sections
511 */
512 for (i = 0; i < eh->e_phnum; i++) {
513 u_long addr = ELF32_NO_ADDR, size = 0;
514 int prot = 0;
515
516 pp = &ph[i];
517
518 switch (ph[i].p_type) {
519 case Elf32_pt_load:
520 elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
521 &ph[i], &addr, &size, &prot);
522 if ((error = elf_set_segment(epp, addr, size,
523 prot)) != 0)
524 goto bad;
525 break;
526
527 case Elf32_pt_shlib:
528 error = ENOEXEC;
529 goto bad;
530
531 case Elf32_pt_interp:
532 /* Already did this one */
533 case Elf32_pt_dynamic:
534 case Elf32_pt_phdr:
535 case Elf32_pt_note:
536 break;
537
538 default:
539 /*
540 * Not fatal, we don't need to understand everything
541 * :-)
542 */
543 break;
544 }
545 }
546
547 /*
548 * Check if we found a dynamically linked binary and arrange to load
549 * it's interpreter
550 */
551 if (interp[0]) {
552 struct elf_args *ap;
553
554 ap = (struct elf_args *) malloc(sizeof(struct elf_args),
555 M_TEMP, M_WAITOK);
556 if ((error = elf_load_file(p, interp, &epp->ep_vmcmds,
557 &epp->ep_entry, ap, &pos)) != 0) {
558 free((char *) ap, M_TEMP);
559 goto bad;
560 }
561 /* Arrange to load the program headers. */
562 pos = ELF_ALIGN(pos + NBPG, NBPG);
563 ap->arg_phaddr = pos;
564 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, phsize,
565 pos, epp->ep_vp, eh->e_phoff,
566 VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
567 pos += phsize;
568
569 ap->arg_phentsize = eh->e_phentsize;
570 ap->arg_phnum = eh->e_phnum;
571 ap->arg_entry = eh->e_entry;
572
573 epp->ep_emul_arg = ap;
574 } else
575 epp->ep_entry = eh->e_entry;
576
577 free((char *) ph, M_TEMP);
578 epp->ep_vp->v_flag |= VTEXT;
579 return exec_aout_setup_stack(p, epp);
580
581 bad:
582 free((char *) ph, M_TEMP);
583 kill_vmcmds(&epp->ep_vmcmds);
584 return ENOEXEC;
585 }
586