FreeBSD/Linux Kernel Cross Reference
sys/kern/exec_macho.c
1 /* $NetBSD: exec_macho.c,v 1.38 2006/07/23 22:06:10 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: exec_macho.c,v 1.38 2006/07/23 22:06:10 ad Exp $");
41
42 #include <sys/param.h>
43 #include <sys/proc.h>
44 #include <sys/malloc.h>
45 #include <sys/namei.h>
46 #include <sys/vnode.h>
47 #include <sys/exec.h>
48 #include <sys/exec_macho.h>
49 #include <sys/syscall.h>
50 #include <sys/signalvar.h>
51 #include <sys/resourcevar.h>
52 #include <sys/mount.h>
53 #include <sys/stat.h>
54
55 #include <uvm/uvm.h>
56
57 #ifdef DEBUG_MACHO
58 #define DPRINTF(a) printf a
59 #else
60 #define DPRINTF(a)
61 #endif
62
63 static int exec_macho_load_segment(struct exec_package *, struct vnode *,
64 u_long, struct exec_macho_segment_command *, int);
65 static int exec_macho_load_dylinker(struct lwp *, struct exec_package *,
66 struct exec_macho_dylinker_command *, u_long *, int);
67 static int exec_macho_load_dylib(struct lwp *, struct exec_package *,
68 struct exec_macho_dylib_command *, int);
69 static u_long exec_macho_load_thread(struct exec_macho_thread_command *);
70 static int exec_macho_load_file(struct lwp *, struct exec_package *,
71 const char *, u_long *, int, int, int);
72 static int exec_macho_load_vnode(struct lwp *, struct exec_package *,
73 struct vnode *, struct exec_macho_fat_header *, u_long *, int, int, int);
74
75 #ifdef DEBUG_MACHO
76 static void
77 exec_macho_print_segment_command(struct exec_macho_segment_command *ls)
78 {
79 printf("ls.cmd 0x%lx\n", ls->cmd);
80 printf("ls.cmdsize 0x%ld\n", ls->cmdsize);
81 printf("ls.segname %s\n", ls->segname);
82 printf("ls.vmaddr 0x%lx\n", ls->vmaddr);
83 printf("ls.vmsize %ld\n", ls->vmsize);
84 printf("ls.fileoff 0x%lx\n", ls->fileoff);
85 printf("ls.filesize %ld\n", ls->filesize);
86 printf("ls.maxprot 0x%x\n", ls->maxprot);
87 printf("ls.initprot 0x%x\n", ls->initprot);
88 printf("ls.nsects %ld\n", ls->nsects);
89 printf("ls.flags 0x%lx\n", ls->flags);
90 }
91
92 static void
93 exec_macho_print_fat_header(struct exec_macho_fat_header *fat)
94 {
95 printf("fat.magic 0x%x\n", be32toh(fat->magic));
96 printf("fat.nfat_arch %d\n", be32toh(fat->nfat_arch));
97 }
98
99 static void
100 exec_macho_print_fat_arch(struct exec_macho_fat_arch *arch)
101 {
102 printf("arch.cputype %x\n", be32toh(arch->cputype));
103 printf("arch.cpusubtype %d\n", be32toh(arch->cpusubtype));
104 printf("arch.offset 0x%x\n", (int32_t)be32toh(arch->offset));
105 printf("arch.size %d\n", (int32_t)be32toh(arch->size));
106 printf("arch.align 0x%x\n", (int32_t)be32toh(arch->align));
107 }
108
109 static void
110 exec_macho_print_object_header(struct exec_macho_object_header *hdr)
111 {
112 printf("hdr.magic 0x%lx\n", hdr->magic);
113 printf("hdr.cputype %x\n", hdr->cputype);
114 printf("hdr.cpusubtype %d\n", hdr->cpusubtype);
115 printf("hdr.filetype 0x%lx\n", hdr->filetype);
116 printf("hdr.ncmds %ld\n", hdr->ncmds);
117 printf("hdr.sizeofcmds %ld\n", hdr->sizeofcmds);
118 printf("hdr.flags 0x%lx\n", hdr->flags);
119 }
120
121 static void
122 exec_macho_print_load_command(struct exec_macho_load_command *lc)
123 {
124 printf("lc.cmd %lx\n", lc->cmd);
125 printf("lc.cmdsize %ld\n", lc->cmdsize);
126 }
127
128 static void
129 exec_macho_print_dylinker_command(struct exec_macho_dylinker_command *dy)
130 {
131 printf("dy.cmd %lx\n", dy->cmd);
132 printf("dy.cmdsize %ld\n", dy->cmdsize);
133 printf("dy.name.offset 0x%lx\n", dy->name.offset);
134 printf("dy.name %s\n", ((char *)dy) + dy->name.offset);
135 }
136
137 static void
138 exec_macho_print_dylib_command(struct exec_macho_dylib_command *dy)
139 {
140 printf("dy.cmd %lx\n", dy->cmd);
141 printf("dy.cmdsize %ld\n", dy->cmdsize);
142 printf("dy.dylib.name.offset 0x%lx\n", dy->dylib.name.offset);
143 printf("dy.dylib.name %s\n", ((char *)dy) + dy->dylib.name.offset);
144 printf("dy.dylib.timestamp %ld\n", dy->dylib.timestamp);
145 printf("dy.dylib.current_version %ld\n", dy->dylib.current_version);
146 printf("dy.dylib.compatibility_version %ld\n",
147 dy->dylib.compatibility_version);
148 }
149
150 static void
151 exec_macho_print_thread_command(struct exec_macho_thread_command *th)
152 {
153 printf("th.cmd %lx\n", th->cmd);
154 printf("th.cmdsize %ld\n", th->cmdsize);
155 printf("th.flavor %ld\n", th->flavor);
156 printf("th.count %ld\n", th->count);
157 }
158 #endif /* DEBUG_MACHO */
159
160 static int
161 exec_macho_load_segment(struct exec_package *epp, struct vnode *vp,
162 u_long foff, struct exec_macho_segment_command *ls, int type)
163 {
164 int flags;
165 struct exec_macho_emul_arg *emea;
166 u_long addr = trunc_page(ls->vmaddr), size = round_page(ls->filesize);
167
168 emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
169
170 flags = VMCMD_BASE;
171
172 #ifdef DEBUG_MACHO
173 exec_macho_print_segment_command(ls);
174 #endif
175 if (strcmp(ls->segname, "__PAGEZERO") == 0)
176 return 0;
177
178 if (strcmp(ls->segname, "__TEXT") != 0 &&
179 strcmp(ls->segname, "__DATA") != 0 &&
180 strcmp(ls->segname, "__LOCK") != 0 &&
181 strcmp(ls->segname, "__OBJC") != 0 &&
182 strcmp(ls->segname, "__CGSERVER") != 0 &&
183 strcmp(ls->segname, "__IMAGE") != 0 &&
184 strcmp(ls->segname, "__LINKEDIT") != 0) {
185 DPRINTF(("Unknown exec_macho segment %s\n", ls->segname));
186 return ENOEXEC;
187 }
188 if (type == MACHO_MOH_EXECUTE) {
189 if (strcmp(ls->segname, "__TEXT") == 0) {
190 epp->ep_taddr = addr;
191 epp->ep_tsize = round_page(ls->vmsize);
192 emea->macho_hdr =
193 (struct exec_macho_object_header *)addr;
194 }
195 if ((strcmp(ls->segname, "__DATA") == 0) ||
196 (strcmp(ls->segname, "__OBJC") == 0) ||
197 (strcmp(ls->segname, "__IMAGE") == 0) ||
198 (strcmp(ls->segname, "__CGSERVER") == 0)) {
199 epp->ep_daddr = addr;
200 epp->ep_dsize = round_page(ls->vmsize);
201 }
202 }
203
204 /*
205 * Some libraries do not have a load base address. The Darwin
206 * kernel seems to skip them, and dyld will do the job.
207 */
208 if (addr == 0)
209 return ENOMEM;
210
211 if (ls->filesize > 0) {
212 NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_pagedvn, size,
213 addr, vp, (off_t)(ls->fileoff + foff),
214 ls->initprot, flags);
215 DPRINTF(("map(0x%lx, 0x%lx, %o, fd@ 0x%lx)\n",
216 addr, size, ls->initprot,
217 ls->fileoff + foff));
218 }
219
220 if (ls->vmsize > size) {
221 addr += size;
222 size = round_page(ls->vmsize - size);
223 NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, size,
224 addr, vp, (off_t)(ls->fileoff + foff),
225 ls->initprot, flags);
226 DPRINTF(("mmap(0x%lx, 0x%lx, %o, zero)\n",
227 ls->vmaddr + ls->filesize, ls->vmsize - ls->filesize,
228 ls->initprot));
229 }
230 return 0;
231 }
232
233
234 static int
235 exec_macho_load_dylinker(struct lwp *l, struct exec_package *epp,
236 struct exec_macho_dylinker_command *dy, u_long *entry, int depth)
237 {
238 struct exec_macho_emul_arg *emea;
239 const char *name = ((const char *)dy) + dy->name.offset;
240 char path[MAXPATHLEN];
241 int error;
242 #ifdef DEBUG_MACHO
243 exec_macho_print_dylinker_command(dy);
244 #endif
245 emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
246
247 (void)snprintf(path, sizeof(path), "%s%s", emea->path, name);
248 DPRINTF(("loading linker %s\n", path));
249 if ((error = exec_macho_load_file(l, epp, path, entry,
250 MACHO_MOH_DYLINKER, 1, depth)) != 0)
251 return error;
252 return 0;
253 }
254
255 static int
256 exec_macho_load_dylib(struct lwp *l, struct exec_package *epp,
257 struct exec_macho_dylib_command *dy, int depth)
258 {
259 struct exec_macho_emul_arg *emea;
260 const char *name = ((const char *)dy) + dy->dylib.name.offset;
261 char path[MAXPATHLEN];
262 int error;
263 u_long entry;
264 #ifdef DEBUG_MACHO
265 exec_macho_print_dylib_command(dy);
266 #endif
267 emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
268 (void)snprintf(path, sizeof(path), "%s%s", emea->path, name);
269 DPRINTF(("loading library %s\n", path));
270 if ((error = exec_macho_load_file(l, epp, path, &entry,
271 MACHO_MOH_DYLIB, 0, depth)) != 0)
272 return error;
273 return 0;
274 }
275
276 static u_long
277 exec_macho_load_thread(struct exec_macho_thread_command *th)
278 {
279 #ifdef DEBUG_MACHO
280 exec_macho_print_thread_command(th);
281 #endif
282 return exec_macho_thread_entry(th);
283 }
284
285 /*
286 * exec_macho_load_file(): Load a macho-binary. This is used
287 * for the dynamic linker and library recursive loading.
288 */
289 static int
290 exec_macho_load_file(struct lwp *l, struct exec_package *epp,
291 const char *path, u_long *entry, int type, int recursive, int depth)
292 {
293 int error;
294 struct nameidata nd;
295 struct vnode *vp;
296 struct vattr attr;
297 struct exec_macho_fat_header fat;
298
299 /*
300 * Check for excessive rercursive loading
301 */
302 if (depth++ > 6)
303 return E2BIG;
304
305 /*
306 * 1. open file
307 * 2. read filehdr
308 * 3. map text, data, and bss out of it using VM_*
309 */
310 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, l);
311 if ((error = namei(&nd)) != 0)
312 return error;
313 vp = nd.ni_vp;
314
315 /*
316 * Similarly, if it's not marked as executable, or it's not a regular
317 * file, we don't allow it to be used.
318 */
319 if (vp->v_type != VREG) {
320 error = EACCES;
321 goto badunlock;
322 }
323
324 error = vn_marktext(vp);
325 if (error)
326 return (error);
327
328 if ((error = VOP_ACCESS(vp, VEXEC, l->l_cred, l)) != 0)
329 goto badunlock;
330
331 /* get attributes */
332 if ((error = VOP_GETATTR(vp, &attr, l->l_cred, l)) != 0)
333 goto badunlock;
334
335 #ifdef notyet /* XXX cgd 960926 */
336 XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
337 #endif
338 VOP_UNLOCK(vp, 0);
339
340 if ((error = exec_read_from(l, vp, 0, &fat, sizeof(fat))) != 0)
341 goto bad;
342
343 if ((error = exec_macho_load_vnode(l, epp, vp, &fat,
344 entry, type, recursive, depth)) != 0)
345 goto bad;
346
347 vrele(vp);
348 return 0;
349
350 badunlock:
351 VOP_UNLOCK(vp, 0);
352
353 bad:
354 #ifdef notyet /* XXX cgd 960926 */
355 (maybe) VOP_CLOSE it
356 #endif
357 vrele(vp);
358 return error;
359 }
360
361 /*
362 * exec_macho_load_vnode(): Map a file from the given vnode.
363 * The fat signature is checked,
364 * and it will return the address of the entry point in entry.
365 * The type determines what we are loading, a dynamic linker,
366 * a dynamic library, or a binary. We use that to guess at
367 * the entry point.
368 */
369 static int
370 exec_macho_load_vnode(struct lwp *l, struct exec_package *epp,
371 struct vnode *vp, struct exec_macho_fat_header *fat, u_long *entry,
372 int type, int recursive, int depth)
373 {
374 u_long aoffs, offs;
375 struct exec_macho_fat_arch arch;
376 struct exec_macho_object_header hdr;
377 struct exec_macho_load_command lc;
378 struct exec_macho_emul_arg *emea;
379 int error = ENOEXEC, i;
380 size_t size;
381 void *bf = &lc;
382 uint32_t *sc = NULL;
383
384 #ifdef DEBUG_MACHO
385 exec_macho_print_fat_header(fat);
386 #endif
387
388 switch (fat->magic) {
389 case MACHO_FAT_MAGIC:
390 for (i = 0; i < be32toh(fat->nfat_arch); i++, arch) {
391 if ((error = exec_read_from(l, vp, sizeof(*fat) +
392 sizeof(arch) * i, &arch, sizeof(arch))) != 0)
393 goto bad;
394 #ifdef DEBUG_MACHO
395 exec_macho_print_fat_arch(&arch);
396 #endif
397 for (sc = exec_macho_supported_cpu; *sc; sc++)
398 if (*sc == be32toh(arch.cputype))
399 break;
400
401 if (sc != NULL)
402 break;
403 }
404 if (sc == NULL || *sc == 0) {
405 DPRINTF(("CPU %d not supported by this binary",
406 be32toh(arch.cputype)));
407 goto bad;
408 }
409 break;
410
411 case MACHO_MOH_MAGIC:
412 /*
413 * This is not a FAT Mach-O binary, the file starts
414 * with the object header.
415 */
416 arch.offset = 0;
417 break;
418
419 default:
420 DPRINTF(("bad exec_macho magic %x\n", fat->magic));
421 goto bad;
422 break;
423 }
424
425 if ((error = exec_read_from(l, vp, be32toh(arch.offset), &hdr,
426 sizeof(hdr))) != 0)
427 goto bad;
428
429 if (hdr.magic != MACHO_MOH_MAGIC) {
430 DPRINTF(("bad exec_macho header magic %lx\n", hdr.magic));
431 goto bad;
432 }
433
434 #ifdef DEBUG_MACHO
435 exec_macho_print_object_header(&hdr);
436 #endif
437 switch (hdr.filetype) {
438 case MACHO_MOH_PRELOAD:
439 case MACHO_MOH_EXECUTE:
440 case MACHO_MOH_DYLINKER:
441 case MACHO_MOH_DYLIB:
442 case MACHO_MOH_BUNDLE:
443 break;
444 default:
445 DPRINTF(("Unsupported exec_macho filetype 0x%lx\n",
446 hdr.filetype));
447 goto bad;
448 }
449
450
451 aoffs = be32toh(arch.offset);
452 offs = aoffs + sizeof(hdr);
453 size = sizeof(lc);
454 for (i = 0; i < hdr.ncmds; i++) {
455 if ((error = exec_read_from(l, vp, offs, &lc, sizeof(lc))) != 0)
456 goto bad;
457
458 #ifdef DEBUG_MACHO
459 exec_macho_print_load_command(&lc);
460 #endif
461 if (size < lc.cmdsize) {
462 if (lc.cmdsize > 4096) {
463 DPRINTF(("Bad command size %ld\n", lc.cmdsize));
464 goto bad;
465 }
466 if (bf != &lc)
467 free(bf, M_TEMP);
468 bf = malloc(size = lc.cmdsize, M_TEMP, M_WAITOK);
469 }
470
471 if ((error = exec_read_from(l, vp, offs, bf, lc.cmdsize)) != 0)
472 goto bad;
473
474 switch (lc.cmd) {
475 case MACHO_LC_SEGMENT:
476 error = exec_macho_load_segment(epp, vp, aoffs,
477 (struct exec_macho_segment_command *)bf, type);
478
479 switch(error) {
480 case ENOMEM: /* Just skip, dyld will load it */
481 DPRINTF(("load segment failed, skipping\n"));
482 i = hdr.ncmds;
483 break;
484 case 0: /* No error, carry on loading file */
485 break;
486 default: /* Abort file load */
487 DPRINTF(("load segment failed, aborting\n"));
488 goto bad;
489 break;
490 }
491 break;
492 case MACHO_LC_LOAD_DYLINKER:
493 if ((error = exec_macho_load_dylinker(l, epp,
494 (struct exec_macho_dylinker_command *)bf,
495 entry, depth)) != 0) {
496 DPRINTF(("load linker failed\n"));
497 goto bad;
498 }
499 emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
500 emea->dynamic = 1;
501 break;
502 case MACHO_LC_LOAD_DYLIB:
503 /*
504 * We should only load libraries required by the
505 * binary we want to load, not libraries required
506 * by theses libraries.
507 */
508 if (recursive == 0)
509 break;
510 if ((error = exec_macho_load_dylib(l, epp,
511 (struct exec_macho_dylib_command *)bf,
512 depth)) != 0) {
513 DPRINTF(("load dylib failed\n"));
514 goto bad;
515 }
516 break;
517
518 case MACHO_LC_THREAD:
519 case MACHO_LC_UNIXTHREAD:
520 if (type == MACHO_MOH_DYLINKER || *entry == 0) {
521 *entry = exec_macho_load_thread(
522 (struct exec_macho_thread_command *)bf);
523 } else {
524 (void)exec_macho_load_thread(
525 (struct exec_macho_thread_command *)bf);
526 }
527 break;
528
529 case MACHO_LC_ID_DYLINKER:
530 case MACHO_LC_ID_DYLIB:
531 case MACHO_LC_SYMTAB:
532 case MACHO_LC_DYSYMTAB:
533 break;
534 default:
535 DPRINTF(("Unhandled exec_macho command 0x%lx\n",
536 lc.cmd));
537 break;
538 }
539 offs += lc.cmdsize;
540 }
541 error = 0;
542 bad:
543 if (bf != &lc)
544 free(bf, M_TEMP);
545 return error;
546 }
547
548 /*
549 * exec_macho_makecmds(): Prepare an Mach-O binary's exec package
550 *
551 * First, set of the various offsets/lengths in the exec package.
552 *
553 * Then, mark the text image busy (so it can be demand paged) or error
554 * out if this is not possible. Finally, set up vmcmds for the
555 * text, data, bss, and stack segments.
556 */
557 int
558 exec_macho_makecmds(struct lwp *l, struct exec_package *epp)
559 {
560 struct exec_macho_fat_header *fat = epp->ep_hdr;
561 struct exec_macho_emul_arg *emea;
562 int error;
563
564 if (epp->ep_hdrvalid < sizeof(*fat))
565 return ENOEXEC;
566
567 /*
568 * Check mount point. Though we're not trying to exec this binary,
569 * we will be executing code from it, so if the mount point
570 * disallows execution or set-id-ness, we punt or kill the set-id.
571 */
572 if (epp->ep_vp->v_mount->mnt_flag & MNT_NOEXEC)
573 return EACCES;
574
575 if (epp->ep_vp->v_mount->mnt_flag & MNT_NOSUID)
576 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
577
578 error = vn_marktext(epp->ep_vp);
579 if (error)
580 return (error);
581
582 emea = malloc(sizeof(struct exec_macho_emul_arg), M_EXEC, M_WAITOK);
583 epp->ep_emul_arg = (void *)emea;
584 emea->dynamic = 0;
585
586 if (!epp->ep_esch->u.mach_probe_func)
587 emea->path = "/";
588 else {
589 if ((error = (*epp->ep_esch->u.mach_probe_func)(&emea->path)) != 0)
590 goto bad2;
591 }
592
593 /*
594 * Make sure the underlying functions will not get
595 * a random value here. 0 means that no entry point
596 * has been found yet.
597 */
598 epp->ep_entry = 0;
599
600 if ((error = exec_macho_load_vnode(l, epp, epp->ep_vp, fat,
601 &epp->ep_entry, MACHO_MOH_EXECUTE, 1, 0)) != 0)
602 goto bad;
603
604 /*
605 * stash a copy of the program name in epp->ep_emul_arg because
606 * we will need it later.
607 */
608 if ((error = copyinstr(epp->ep_name, emea->filename,
609 MAXPATHLEN, NULL)) != 0) {
610 DPRINTF(("Copyinstr %p failed\n", epp->ep_name));
611 goto bad;
612 }
613
614 return (*epp->ep_esch->es_setup_stack)(l, epp);
615 bad:
616 kill_vmcmds(&epp->ep_vmcmds);
617 bad2:
618 free(emea, M_EXEC);
619 return error;
620 }
Cache object: dd406b5e27785b77ff5d1c332704843a
|