]> git.saurik.com Git - apple/xnu.git/blob - libsa/load.c
2ffba7e7d55e6429d1f30e0ed078b42fa2189148
[apple/xnu.git] / libsa / load.c
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30
31 /***************
32 * HEADERS
33 ***************/
34 #ifndef KERNEL
35
36 #include <CoreFoundation/CoreFoundation.h>
37
38 #include <libc.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <unistd.h>
44
45 #include <sys/stat.h>
46 #include <sys/file.h>
47 #include <sys/param.h>
48 #include <sys/types.h>
49 #include <sys/mman.h>
50
51 #include <mach/mach_types.h>
52 #include <mach/mach.h>
53 #include <mach/mach_init.h>
54 #include <mach/mach_error.h>
55 #include <mach/mach_host.h>
56 #include <mach/mach_port.h>
57 #include <mach-o/kld.h>
58 #include <mach-o/arch.h>
59 #include <mach-o/fat.h>
60 #include <mach-o/loader.h>
61 #include <mach-o/nlist.h>
62 #include <kern/kern_types.h>
63 #include <kern/kalloc.h>
64 #include <libkern/OSByteOrder.h>
65
66 #include "vers_rsrc.h"
67
68 #else
69
70 #include <mach-o/kld.h>
71 #include <mach-o/loader.h>
72 #include <mach-o/nlist.h>
73 #include <libsa/vers_rsrc.h>
74
75 #endif /* not KERNEL */
76
77 #include "load.h"
78 #include "dgraph.h"
79 #include "kld_patch.h"
80
81 /***************
82 * MACROS
83 ***************/
84
85 #ifndef KERNEL
86
87 #define PRIV_EXT
88
89 #else
90
91 #define PRIV_EXT __private_extern__
92
93 #ifdef DEBUG
94 #define LOG_DELAY(x) IODelay((x) * 1000000)
95 #define VTYELLOW "\033[33m"
96 #define VTRESET "\033[0m"
97 #else
98 #define LOG_DELAY()
99 #define VTYELLOW
100 #define VTRESET
101 #endif /* DEBUG */
102
103 #endif /* not KERNEL */
104
105 /***************
106 * FUNCTION PROTOS
107 ***************/
108
109 #ifdef KERNEL
110 extern kern_return_t
111 kmod_create_internal(
112 kmod_info_t *info,
113 kmod_t *id);
114
115 extern kern_return_t
116 kmod_destroy_internal(kmod_t id);
117
118 extern kern_return_t
119 kmod_start_or_stop(
120 kmod_t id,
121 int start,
122 kmod_args_t *data,
123 mach_msg_type_number_t *dataCount);
124
125 extern kern_return_t kmod_retain(kmod_t id);
126 extern kern_return_t kmod_release(kmod_t id);
127
128 extern struct mach_header _mh_execute_header;
129 #endif /* KERNEL */
130
131
132 // Used to pass info between kld library and callbacks
133 static dgraph_entry_t * G_current_load_entry = NULL;
134
135 #ifndef KERNEL
136 static mach_port_t G_kernel_port = PORT_NULL;
137 static mach_port_t G_kernel_priv_port = PORT_NULL;
138 static int G_syms_only;
139
140 static kload_error
141 register_prelink(dgraph_entry_t * entry,
142 kmod_info_t * local_kmod_info, vm_offset_t kernel_kmod_info);
143
144 struct PrelinkState
145 {
146 kmod_info_t modules[1];
147 };
148 struct PrelinkState * G_prelink;
149 CFMutableDataRef G_prelink_data;
150 CFMutableDataRef G_prelink_dependencies;
151
152 #endif /* not KERNEL */
153
154 // used by dgraph.c so can't be static
155 kload_log_level log_level = 0;
156
157 #ifndef KERNEL
158 static void __kload_null_log(const char * format, ...);
159 static void __kload_null_err_log(const char * format, ...);
160 static int __kload_null_approve(int default_answer, const char * format, ...);
161 static int __kload_null_veto(int default_answer, const char * format, ...);
162 static const char * __kload_null_input(const char * format, ...);
163
164 void (*__kload_log_func)(const char * format, ...) =
165 &__kload_null_log;
166 void (*__kload_err_log_func)(const char * format, ...) = &__kload_null_err_log;
167 int (*__kload_approve_func)(int default_answer,
168 const char * format, ...) = &__kload_null_approve;
169 int (*__kload_veto_func)(int default_answer,
170 const char * format, ...) = &__kload_null_veto;
171 const char * (*__kload_input_func)(const char * format, ...) =
172 &__kload_null_input;
173 #endif /* not KERNEL */
174
175 static unsigned long __kload_linkedit_address(
176 unsigned long size,
177 unsigned long headers_size);
178 static void __kload_clean_up_entry(dgraph_entry_t * entry);
179 static void __kload_clear_kld_globals(void);
180 static kload_error __kload_patch_dgraph(dgraph_t * dgraph
181 #ifndef KERNEL
182 ,
183 const char * kernel_file
184 #endif /* not KERNEL */
185 );
186 static kload_error __kload_load_modules(dgraph_t * dgraph
187 #ifndef KERNEL
188 ,
189 const char * kernel_file,
190 const char * patch_file, const char * patch_dir,
191 const char * symbol_file, const char * symbol_dir,
192 int do_load, int do_start_kmod, int do_prelink,
193 int interactive_level,
194 int ask_overwrite_symbols, int overwrite_symbols
195 #endif /* not KERNEL */
196 );
197
198 static kload_error __kload_check_module_loaded(
199 dgraph_t * dgraph,
200 dgraph_entry_t * entry,
201 #ifndef KERNEL
202 kmod_info_t * kmod_list,
203 #endif /* not KERNEL */
204 int log_if_already);
205
206 static kload_error __kload_load_module(dgraph_t * dgraph,
207 dgraph_entry_t * entry,
208 int is_root
209 #ifndef KERNEL
210 ,
211 const char * symbol_file,
212 const char * symbol_dir,
213 int do_load,
214 int interactive_level,
215 int ask_overwrite_symbols,
216 int overwrite_symbols
217 #endif /* not KERNEL */
218 );
219 static kload_error __kload_set_module_dependencies(dgraph_entry_t * entry);
220 static kload_error __kload_start_module(dgraph_entry_t * entry);
221
222 #ifndef KERNEL
223 static kload_error __kload_output_patches(
224 dgraph_t * dgraph,
225 const char * patch_file,
226 const char * patch_dir,
227 int ask_overwrite_symbols,
228 int overwrite_symbols);
229
230 Boolean _IOReadBytesFromFile(CFAllocatorRef alloc, const char *path, void **bytes,
231 CFIndex *length, CFIndex maxLength);
232 Boolean _IOWriteBytesToFile(const char *path, const void *bytes, CFIndex length);
233
234 #endif /* not KERNEL */
235
236 /*******************************************************************************
237 *
238 *******************************************************************************/
239 PRIV_EXT
240 kload_error kload_load_dgraph(dgraph_t * dgraph
241 #ifndef KERNEL
242 ,
243 const char * kernel_file,
244 const char * patch_file, const char * patch_dir,
245 const char * symbol_file, const char * symbol_dir,
246 int do_load, int do_start_kmod, int do_prelink,
247 int interactive_level,
248 int ask_overwrite_symbols, int overwrite_symbols
249 #endif /* not KERNEL */
250 )
251 {
252 kload_error result = kload_error_none;
253 int one_has_address = 0;
254 int one_lacks_address = 0;
255 unsigned int i;
256 #ifndef KERNEL
257 int syms_only;
258
259 syms_only = (!do_load) && (symbol_dir || symbol_file);
260
261 if (log_level >= kload_log_level_load_details) {
262 kload_log_message("loading dependency graph:" KNL);
263 dgraph_log(dgraph);
264 }
265
266 if (syms_only && log_level >= kload_log_level_load_details) {
267 kload_log_message("loading for symbol generation only" KNL);
268 }
269
270 /*****
271 * If we're not loading and have no request to emit a symbol
272 * or patch file, there's nothing to do!
273 */
274 if (!do_load && !symbol_dir && !symbol_file &&
275 !patch_dir && !patch_file) {
276
277 if (syms_only && log_level >= kload_log_level_load_details) {
278 kload_log_message("loader has no work to do" KNL);
279 }
280
281 result = kload_error_none; // fixme: should this be USAGE error?
282 goto finish;
283 }
284
285 /*****
286 * If we're doing symbols only, then all entries in the dgraph must
287 * have addresses assigned, or none must.
288 */
289 if (syms_only) {
290 if (log_level >= kload_log_level_load_details) {
291 kload_log_message("checking whether modules have addresses assigned" KNL);
292 }
293 for (i = 0; i < dgraph->length; i++) {
294 struct dgraph_entry_t * entry = dgraph->load_order[i];
295 if (entry->is_kernel_component) {
296 continue;
297 }
298 if (entry->loaded_address != 0) {
299 one_has_address = 1;
300 } else {
301 one_lacks_address = 1;
302 }
303 }
304 }
305 #endif /* not KERNEL */
306
307 if (one_has_address && one_lacks_address) {
308 kload_log_error(
309 "either all modules must have addresses set to nonzero values or "
310 "none must" KNL);
311 result = kload_error_invalid_argument;
312 goto finish;
313 }
314
315 #ifndef KERNEL
316 /* we need the priv port to check/load modules in the kernel.
317 */
318 if (PORT_NULL == G_kernel_priv_port) {
319 G_kernel_priv_port = mach_host_self(); /* if we are privileged */
320 }
321 #endif /* not KERNEL */
322
323 /*****
324 * In the kernel, ALWAYS get load addresses of existing loaded kmods.
325 */
326 #ifndef KERNEL
327 /*****
328 * If we don't have addresses, then get them from the kernel.
329 */
330 if (!one_has_address && !do_prelink && (do_load || symbol_file || symbol_dir)) {
331 #endif /* not KERNEL */
332 if (log_level >= kload_log_level_load_details) {
333 kload_log_message("getting module addresses from kernel" KNL);
334 }
335 #ifndef KERNEL
336 result = kload_set_load_addresses_from_kernel(dgraph, kernel_file,
337 do_load);
338 #else
339 result = kload_set_load_addresses_from_kernel(dgraph);
340 #endif /* not KERNEL */
341 if (result == kload_error_already_loaded) {
342
343 #ifndef KERNEL
344 if (do_load) {
345 goto finish;
346 }
347 #else
348 goto finish;
349 #endif /* not KERNEL */
350
351 } else if (result != kload_error_none) {
352 kload_log_error("can't check load addresses of modules" KNL);
353 goto finish;
354 }
355 #ifndef KERNEL
356 }
357 #endif /* not KERNEL */
358
359 #ifndef KERNEL
360 /*****
361 * At this point, if we're doing symbols only, it's an error to not
362 * have a load address for every module.
363 */
364 if (syms_only && !do_prelink) {
365 if (log_level >= kload_log_level_load_details) {
366 kload_log_message("checking that all modules have addresses assigned" KNL);
367 }
368 for (i = 0; i < dgraph->length; i++) {
369 struct dgraph_entry_t * entry = dgraph->load_order[i];
370 if (entry->is_kernel_component) {
371 continue;
372 }
373 if (!entry->loaded_address) {
374 kload_log_error(
375 "missing load address during symbol generation: %s" KNL,
376 entry->name);
377 result = kload_error_unspecified;
378 goto finish;
379 }
380 }
381 }
382
383 if (do_prelink)
384 {
385 void * bytes;
386 CFIndex length;
387 CFAllocatorRef alloc;
388
389 // We need a real allocator to pass to _IOReadBytesFromFile
390 alloc = CFRetain(CFAllocatorGetDefault());
391 if (_IOReadBytesFromFile(alloc, "prelinkstate", &bytes, &length, 0))
392 {
393 G_prelink_data = CFDataCreateMutable(alloc, 0);
394 CFDataAppendBytes(G_prelink_data, (UInt8 *) bytes, length);
395 CFAllocatorDeallocate(alloc, bytes);
396 }
397 G_prelink_dependencies = CFDataCreateMutable(alloc, 0);
398 if (_IOReadBytesFromFile(alloc, "prelinkdependencies", &bytes, &length, 0))
399 {
400 CFDataAppendBytes(G_prelink_dependencies, (UInt8 *) bytes, length);
401 CFAllocatorDeallocate(alloc, bytes);
402 }
403 CFRelease(alloc);
404
405 if (!G_prelink_data) {
406 kload_log_error(
407 "can't get load address for prelink %s" KNL, kernel_file);
408 result = kload_error_link_load;
409 goto finish;
410 }
411 else
412 G_prelink = (struct PrelinkState *) CFDataGetMutableBytePtr(G_prelink_data);
413 }
414 else
415 G_prelink = 0;
416 #endif /* not KERNEL */
417
418 #ifndef KERNEL
419
420 result = __kload_load_modules(dgraph, kernel_file,
421 patch_file, patch_dir, symbol_file, symbol_dir,
422 do_load, do_start_kmod, do_prelink, interactive_level,
423 ask_overwrite_symbols, overwrite_symbols);
424 #else
425 result = __kload_load_modules(dgraph);
426 #endif /* not KERNEL */
427
428 finish:
429
430 #ifndef KERNEL
431 /* Dispose of the host port to prevent security breaches and port
432 * leaks. We don't care about the kern_return_t value of this
433 * call for now as there's nothing we can do if it fails.
434 */
435 if (PORT_NULL != G_kernel_priv_port) {
436 mach_port_deallocate(mach_task_self(), G_kernel_priv_port);
437 G_kernel_priv_port = PORT_NULL;
438 }
439 #endif /* not KERNEL */
440
441 for (i = 0; i < dgraph->length; i++) {
442 dgraph_entry_t * current_entry = dgraph->graph[i];
443 __kload_clean_up_entry(current_entry);
444 }
445
446 #ifndef KERNEL
447 if (G_prelink)
448 {
449 SInt32 length;
450 const void * bytes;
451 Boolean success;
452
453 length = CFDataGetLength(G_prelink_data);
454 bytes = (0 == length) ? (const void *)"" : CFDataGetBytePtr(G_prelink_data);
455 success = _IOWriteBytesToFile("prelinkstate", bytes, length);
456 if (!success)
457 {
458 kload_log_error("write prelinkstate" KNL);
459 result = kload_error_link_load;
460 }
461 length = CFDataGetLength(G_prelink_dependencies);
462 bytes = (0 == length) ? (const void *)"" : CFDataGetBytePtr(G_prelink_dependencies);
463 success = _IOWriteBytesToFile("prelinkdependencies", bytes, length);
464 if (!success)
465 {
466 kload_log_error("write prelinkdependencies" KNL);
467 result = kload_error_link_load;
468 }
469 }
470 #endif /* not KERNEL */
471
472 return result;
473 }
474
475 #ifndef KERNEL
476 /*******************************************************************************
477 * This function claims the option flags d and D for object file dependencies
478 * and in-kernel dependencies, respectively.
479 *******************************************************************************/
480 kload_error kload_load_with_arglist(
481 int argc, char **argv,
482 const char * kernel_file,
483 const char * patch_file, const char * patch_dir,
484 const char * symbol_file, const char * symbol_dir,
485 int do_load, int do_start_kmod,
486 int interactive_level,
487 int ask_overwrite_symbols, int overwrite_symbols)
488 {
489 kload_error result = kload_error_none;
490 dgraph_error_t dgraph_result;
491 int syms_only = (!do_load) && (symbol_file || symbol_dir);
492
493 static dgraph_t dependency_graph;
494
495 /* Zero out fields in dependency graph for proper error handling later.
496 */
497 bzero(&dependency_graph, sizeof(dependency_graph));
498
499 dgraph_result = dgraph_init_with_arglist(&dependency_graph,
500 syms_only, "-d", "-D", argc, argv);
501 if (dgraph_result == dgraph_error) {
502 kload_log_error("error processing dependency list" KNL);
503 result = kload_error_unspecified;
504 goto finish;
505 } else if (dgraph_result == dgraph_invalid) {
506 // anything to print here, or did init call print something?
507 result = kload_error_invalid_argument;
508 goto finish;
509 }
510
511 result = kload_load_dgraph(&dependency_graph, kernel_file,
512 patch_file, patch_dir, symbol_file, symbol_dir,
513 do_load, do_start_kmod, false /* do_prelink */, interactive_level,
514 ask_overwrite_symbols, overwrite_symbols);
515
516 finish:
517 return result;
518 }
519 #endif /* not KERNEL */
520 /*******************************************************************************
521 * This function can only operate on 32 bit mach object file symbol table
522 * entries.
523 *******************************************************************************/
524 static
525 kload_error __kload_keep_symbols(dgraph_entry_t * entry)
526 {
527 struct mach_header * hdr;
528 struct segment_command * seg;
529 struct nlist * sym;
530 struct symtab_command * symcmd;
531 unsigned long idx, ncmds;
532 vm_size_t size;
533 vm_address_t mem;
534
535 if (entry->symbols)
536 return kload_error_none;
537
538 hdr = entry->linked_image;
539 ncmds = hdr->ncmds;
540 seg = (struct segment_command *)(hdr + 1);
541 for (idx = 0;
542 idx < ncmds;
543 idx++, seg = (struct segment_command *)(((vm_offset_t)seg) + seg->cmdsize))
544 {
545 if (LC_SYMTAB == seg->cmd)
546 break;
547 }
548 if (idx >= ncmds)
549 {
550 kload_log_error("no LC_SYMTAB" KNL);
551 return kload_error_unspecified;
552 }
553
554 symcmd = (struct symtab_command *) seg;
555
556 struct load_cmds {
557 struct mach_header hdr;
558 struct segment_command seg;
559 struct symtab_command symcmd;
560 };
561 struct load_cmds * cmd;
562 unsigned int symtabsize;
563
564 symtabsize = symcmd->stroff + symcmd->strsize - symcmd->symoff;
565
566 size = sizeof(struct load_cmds) + symtabsize;
567
568 mem = (vm_offset_t) malloc(size);
569
570 cmd = (struct load_cmds *) mem;
571 sym = (struct nlist *) (cmd + 1);
572
573 cmd->hdr = *hdr;
574 cmd->symcmd = *symcmd;
575 bcopy((const void *) (((vm_offset_t) hdr) + symcmd->symoff),
576 sym,
577 symtabsize);
578
579 hdr = (struct mach_header *) mem;
580 cmd->hdr.ncmds = 2;
581 cmd->hdr.sizeofcmds = sizeof(struct load_cmds) - sizeof(struct mach_header);
582 cmd->hdr.flags &= ~MH_INCRLINK;
583
584 cmd->symcmd.stroff -= (symcmd->symoff - sizeof(struct load_cmds));
585 cmd->symcmd.symoff = sizeof(struct load_cmds);
586
587 cmd->seg.cmd = LC_SEGMENT;
588 cmd->seg.cmdsize = sizeof(struct segment_command);
589 strcpy(cmd->seg.segname, SEG_LINKEDIT);
590 cmd->seg.vmaddr = 0;
591 cmd->seg.vmsize = 0;
592 cmd->seg.fileoff = cmd->symcmd.symoff;
593 cmd->seg.filesize = symtabsize;
594 cmd->seg.maxprot = 7;
595 cmd->seg.initprot = 1;
596 cmd->seg.nsects = 0;
597 cmd->seg.flags = 0;
598
599 sym = (struct nlist *) (cmd + 1);
600 for (idx = 0; idx < symcmd->nsyms; idx++, sym++)
601 {
602 if ( (sym->n_type & N_STAB) != 0)
603 {
604 sym->n_type = N_ABS;
605 sym->n_desc = 0;
606 sym->n_value = sym->n_un.n_strx;
607 sym->n_un.n_strx = 0;
608 sym->n_sect = NO_SECT;
609 }
610 else if ( (sym->n_type & N_TYPE) == N_SECT)
611 {
612 sym->n_sect = NO_SECT;
613 sym->n_type = (sym->n_type & ~N_TYPE) | N_ABS;
614 }
615 }
616 if (log_level >= kload_log_level_load_details)
617 {
618 kload_log_message("__kload_keep_symbols %s, nsyms %ld, 0x%x bytes" KNL,
619 entry->name, symcmd->nsyms, size);
620 }
621
622 entry->symbols = mem;
623 entry->symbols_malloc = mem;
624 entry->symbols_length = size;
625
626 return kload_error_none;
627 }
628
629
630 /*******************************************************************************
631 * This function can only operate on 32 bit mach object files
632 *******************************************************************************/
633 static
634 kload_error __kload_make_opaque_basefile(dgraph_t * dgraph, struct mach_header * hdr)
635 {
636 struct segment_command * seg;
637 struct segment_command * data_seg;
638 struct segment_command * text_seg;
639 struct section * sec;
640 unsigned int j;
641 vm_offset_t offset;
642 unsigned long idx, ncmds;
643 vm_size_t size;
644 vm_address_t mem, out;
645 static vm_address_t keep_base_image;
646 static vm_size_t keep_base_size;
647
648 if (dgraph->opaque_base_image)
649 return kload_error_none;
650
651 if (keep_base_image)
652 {
653 dgraph->opaque_base_image = keep_base_image;
654 dgraph->opaque_base_length = keep_base_size;
655 return kload_error_none;
656 }
657
658 data_seg = text_seg = NULL;
659 ncmds = hdr->ncmds;
660 seg = (struct segment_command *)(hdr + 1);
661 for (idx = 0;
662 idx < ncmds;
663 idx++, seg = (struct segment_command *)(((vm_offset_t)seg) + seg->cmdsize))
664 {
665 if (LC_SEGMENT != seg->cmd)
666 continue;
667 if (!strcmp(SEG_TEXT, seg->segname))
668 text_seg = seg;
669 else if (!strcmp(SEG_DATA, seg->segname))
670 data_seg = seg;
671 }
672 if (!text_seg || !data_seg)
673 {
674 kload_log_error("no SEG_TEXT or SEG_DATA" KNL);
675 return kload_error_unspecified;
676 }
677
678 size = sizeof(struct mach_header) + text_seg->cmdsize + data_seg->cmdsize;
679 mem = (vm_offset_t) malloc(size);
680
681 out = mem;
682 bcopy(hdr, (void *) out, sizeof(struct mach_header));
683 hdr = (struct mach_header *) out;
684 out += sizeof(struct mach_header);
685
686 bcopy(text_seg, (void *) out, text_seg->cmdsize);
687 text_seg = (struct segment_command *) out;
688 out += text_seg->cmdsize;
689
690 bcopy(data_seg, (void *) out, data_seg->cmdsize);
691 data_seg = (struct segment_command *) out;
692 out += data_seg->cmdsize;
693
694 hdr->ncmds = 2;
695 hdr->sizeofcmds = text_seg->cmdsize + data_seg->cmdsize;
696
697 offset = hdr->sizeofcmds;
698
699 text_seg->fileoff = offset;
700 text_seg->filesize = 0;
701
702 sec = (struct section *)(text_seg + 1);
703 for (j = 0; j < text_seg->nsects; j++, sec++)
704 {
705 // sec->addr = (unsigned long) addr;
706 sec->size = 0;
707 sec->offset = offset;
708 sec->nreloc = 0;
709 }
710
711 data_seg->fileoff = offset;
712 data_seg->filesize = 0;
713
714 sec = (struct section *)(data_seg + 1);
715 for (j = 0; j < data_seg->nsects; j++, sec++)
716 {
717 // sec->addr = (unsigned long) addr;
718 sec->size = 0;
719 sec->offset = offset;
720 sec->nreloc = 0;
721 }
722
723 dgraph->opaque_base_image = mem;
724 dgraph->opaque_base_length = size;
725 keep_base_image = mem;
726 keep_base_size = size;
727
728 return kload_error_none;
729 }
730
731 /*******************************************************************************
732 *
733 *******************************************************************************/
734 static
735 kload_error __kload_load_modules(dgraph_t * dgraph
736 #ifndef KERNEL
737 ,
738 const char * kernel_file,
739 const char * patch_file,
740 const char * patch_dir,
741 const char * symbol_file,
742 const char * symbol_dir,
743 int do_load,
744 int do_start_kmod,
745 int do_prelink,
746 int interactive_level,
747 int ask_overwrite_symbols,
748 int overwrite_symbols
749 #endif /* not KERNEL */
750 )
751 {
752 kload_error result = kload_error_none;
753 #ifndef KERNEL
754 long int kernel_size = 0;
755 kern_return_t mach_result = KERN_SUCCESS;
756 #endif /* not KERNEL */
757 char * kernel_base_addr = 0;
758 int kld_result;
759 Boolean cleanup_kld_loader = false;
760 unsigned int i;
761
762 /* We have to map all object files to get their CFBundleIdentifier
763 * names.
764 */
765 #ifndef KERNEL
766 result = kload_map_dgraph(dgraph, kernel_file);
767 #else
768 result = kload_map_dgraph(dgraph);
769 #endif /* not KERNEL */
770 if (result != kload_error_none) {
771 kload_log_error("error mapping object files" KNL);
772 goto finish;
773 }
774
775 #ifndef KERNEL
776 result = __kload_patch_dgraph(dgraph, kernel_file);
777 #else
778 result = __kload_patch_dgraph(dgraph);
779 #endif /* not KERNEL */
780 if (result != kload_error_none) {
781 // FIXME: print an error message here?
782 goto finish;
783 }
784
785 #ifndef KERNEL
786 // FIXME: check error return
787 __kload_output_patches(dgraph, patch_file, patch_dir,
788 ask_overwrite_symbols, overwrite_symbols);
789
790 /*****
791 * If we're not loading or writing symbols, we're done.
792 */
793 if (!do_load && !do_prelink && !symbol_file && !symbol_dir) {
794 goto finish;
795 }
796
797 if (do_load && PORT_NULL == G_kernel_port) {
798 mach_result = task_for_pid(mach_task_self(), 0, &G_kernel_port);
799 if (mach_result != KERN_SUCCESS) {
800 kload_log_error("unable to get kernel task port: %s" KNL,
801 mach_error_string(mach_result));
802 kload_log_error("you must be running as root to load "
803 "modules into the kernel" KNL);
804 result = kload_error_kernel_permission;
805 goto finish;
806 }
807 }
808 #endif /* not KERNEL */
809
810 kld_address_func(&__kload_linkedit_address);
811
812 #ifndef KERNEL
813 G_syms_only = (!do_load) && (symbol_file || symbol_dir || patch_dir);
814
815 kernel_base_addr = kld_file_getaddr(kernel_file, &kernel_size);
816 if (!kernel_base_addr) {
817 kload_log_error(
818 "can't get load address for kernel %s" KNL, kernel_file);
819 result = kload_error_link_load;
820 goto finish;
821 }
822 #else /* KERNEL */
823
824 const char * kernel_file = "(kernel)";
825 kernel_base_addr = (char *) &_mh_execute_header;
826
827 #endif /* not KERNEL */
828
829 kld_result = true;
830 if (dgraph->has_symbol_sets)
831 {
832 result = __kload_make_opaque_basefile(dgraph, (struct mach_header *) kernel_base_addr);
833 if (result != kload_error_none) {
834 kload_log_error("can't construct opaque base image from %s" KNL, kernel_file);
835 goto finish;
836 }
837
838 kld_result = kld_load_basefile_from_memory(kernel_file,
839 (char *) dgraph->opaque_base_image,
840 dgraph->opaque_base_length);
841 }
842 #ifndef KERNEL
843 else
844 kld_result = kld_load_basefile_from_memory(kernel_file,
845 (char *) kernel_base_addr, kernel_size);
846 #endif /* not KERNEL */
847
848 if (!kld_result) {
849 kload_log_error("can't link base image %s" KNL, kernel_file);
850 result = kload_error_link_load;
851 goto finish;
852 }
853
854 cleanup_kld_loader = true;
855 char opaque_now = false;
856
857 for (i = 0; i < dgraph->length; i++) {
858 dgraph_entry_t * current_entry = dgraph->load_order[i];
859
860 opaque_now |= current_entry->opaque_link;
861
862 if (kOpaqueLink & opaque_now)
863 {
864 unsigned int k, j;
865
866 if (log_level >= kload_log_level_load_details)
867 {
868 kload_log_message("opaque link for %s" KNL, current_entry->name);
869 }
870
871 kld_set_link_options(KLD_STRIP_ALL); // KLD_STRIP_NONE
872
873 if (dgraph->have_loaded_symbols)
874 {
875 kld_unload_all(1);
876 if (kRawKernelLink & current_entry->opaque_link) {
877 #ifndef KERNEL
878 kld_result = kld_load_basefile_from_memory(kernel_file,
879 (char *) kernel_base_addr, kernel_size);
880 #endif
881 } else {
882 kld_result = kld_load_basefile_from_memory(kernel_file,
883 (char *) dgraph->opaque_base_image,
884 dgraph->opaque_base_length);
885 dgraph->have_loaded_symbols = false;
886 }
887 if (!kld_result) {
888 kload_log_error("can't link base image %s" KNL, kernel_file);
889 result = kload_error_link_load;
890 goto finish;
891 }
892 }
893
894 for (j = 0; j < i; j++)
895 {
896
897 dgraph_entry_t * image_dep = dgraph->load_order[j];
898
899 if (current_entry->opaque_link)
900 {
901 for (k = 0;
902 (k < current_entry->num_dependencies)
903 && (current_entry->dependencies[k] != image_dep);
904 k++) {}
905
906 if (k == current_entry->num_dependencies)
907 continue;
908 }
909
910 if (!current_entry->opaque_link && image_dep->opaques)
911 {
912 // kpi not on direct dependency list
913 continue;
914 }
915 if (kRawKernelLink & image_dep->opaques)
916 {
917 // raw kernel already in base image
918 continue;
919 }
920
921 if (!image_dep->symbols)
922 {
923 kload_log_error("internal error; no dependent symbols" KNL);
924 result = kload_error_link_load;
925 goto finish;
926 }
927 else
928 {
929 struct mach_header * kld_header;
930
931 #ifndef KERNEL
932 kld_result = kld_load_from_memory(&kld_header, image_dep->name,
933 (char *) image_dep->symbols, image_dep->symbols_length, NULL);
934 #else
935 kld_result = kld_load_from_memory(&kld_header, image_dep->name,
936 (char *) image_dep->symbols, image_dep->symbols_length);
937 #endif /* not KERNEL */
938 if (!kld_result) {
939 kload_log_error("can't link dependent image %s" KNL, image_dep->name);
940 result = kload_error_link_load;
941 goto finish;
942 }
943 kld_forget_symbol("_kmod_info");
944 dgraph->have_loaded_symbols = true;
945 }
946 }
947 } /* opaque_now */
948
949 if (dgraph->has_opaque_links
950 #ifndef KERNEL
951 || symbol_file || symbol_dir
952 #endif
953 )
954 kld_set_link_options(KLD_STRIP_NONE);
955 else
956 kld_set_link_options(KLD_STRIP_ALL);
957
958 #ifndef KERNEL
959 result = __kload_load_module(dgraph, current_entry,
960 (current_entry == dgraph->root),
961 symbol_file, symbol_dir, do_load,
962 interactive_level, ask_overwrite_symbols, overwrite_symbols);
963 #else
964 result = __kload_load_module(dgraph, current_entry,
965 (current_entry == dgraph->root));
966 #endif /* not KERNEL */
967 if (result != kload_error_none) {
968 goto finish;
969 }
970
971 if (dgraph->has_opaque_links && (current_entry != dgraph->root))
972 {
973 if (!(kRawKernelLink & current_entry->opaques)) {
974 result = __kload_keep_symbols(current_entry);
975 }
976 if (result != kload_error_none) {
977 kload_log_error("__kload_keep_symbols() failed for module %s" KNL,
978 current_entry->name);
979 goto finish;
980 }
981 }
982
983 #ifndef KERNEL
984 if (do_load && current_entry->do_load) {
985 #else
986 if (current_entry->do_load) {
987 #endif /* not KERNEL */
988 result = __kload_set_module_dependencies(current_entry);
989 if ( ! (result == kload_error_none ||
990 result == kload_error_already_loaded) ) {
991 goto finish;
992 }
993
994 #ifndef KERNEL
995 if ( (interactive_level == 1 && current_entry == dgraph->root) ||
996 (interactive_level == 2) ) {
997
998 int approve = (*__kload_approve_func)(1,
999 "\nStart module %s (ansering no will abort the load)",
1000 current_entry->name);
1001
1002 if (approve > 0) {
1003 do_start_kmod = true; // override 'cause user said so
1004 } else {
1005 kern_return_t mach_result;
1006 if (approve < 0) {
1007 kload_log_message("error reading user response; "
1008 "destroying loaded module" KNL);
1009 } else {
1010 kload_log_message("user canceled module start; "
1011 "destroying loaded module" KNL);
1012 }
1013 mach_result = kmod_destroy(G_kernel_priv_port, current_entry->kmod_id);
1014 if (mach_result != KERN_SUCCESS) {
1015 kload_log_error("kmod_destroy() failed" KNL);
1016 }
1017 if (approve < 0) {
1018 result = kload_error_unspecified;
1019 goto finish;
1020 } else {
1021 result = kload_error_user_abort;
1022 goto finish;
1023 }
1024 }
1025 }
1026 #endif /* not KERNEL */
1027
1028 #ifndef KERNEL
1029 if (current_entry != dgraph->root ||
1030 (current_entry == dgraph->root && do_start_kmod)) {
1031 #endif /* not KERNEL */
1032
1033 result = __kload_start_module(current_entry);
1034 if ( ! (result == kload_error_none ||
1035 result == kload_error_already_loaded) ) {
1036 goto finish;
1037 #ifndef KERNEL
1038 } else if (interactive_level ||
1039 log_level >= kload_log_level_load_details) {
1040 #else
1041 } else if (log_level >= kload_log_level_load_details) {
1042 #endif /* not KERNEL */
1043
1044 kload_log_message("started module %s" KNL,
1045 current_entry->name);
1046 } /* log_level */
1047 #ifndef KERNEL
1048 } /* current_entry... */
1049 #endif /* not KERNEL */
1050
1051
1052 #ifndef KERNEL
1053 } /* if do_load */
1054 #else
1055 } /* if do_load */
1056 #endif /* not KERNEL */
1057 } /* for i, dgraph->length */
1058
1059 finish:
1060
1061 #ifndef KERNEL
1062 /* Dispose of the kernel port to prevent security breaches and port
1063 * leaks. We don't care about the kern_return_t value of this
1064 * call for now as there's nothing we can do if it fails.
1065 */
1066 if (PORT_NULL != G_kernel_port) {
1067 mach_port_deallocate(mach_task_self(), G_kernel_port);
1068 G_kernel_port = PORT_NULL;
1069 }
1070 #endif /* not KERNEL */
1071
1072 if (cleanup_kld_loader) {
1073 kld_unload_all(1);
1074 }
1075
1076 return result;
1077 }
1078
1079
1080 /*******************************************************************************
1081 *
1082 *******************************************************************************/
1083
1084 #ifndef KERNEL
1085 #define __KLOAD_SYMBOL_EXTENSION ".sym"
1086 #endif /* not KERNEL */
1087
1088 static
1089 kload_error __kload_load_module(dgraph_t * dgraph,
1090 dgraph_entry_t * entry,
1091 #ifdef KERNEL
1092 __unused int is_root
1093 #else /* not KERNEL */
1094 int is_root,
1095 const char * symbol_file,
1096 const char * symbol_dir,
1097 int do_load,
1098 int interactive_level,
1099 int ask_overwrite_symbols,
1100 int overwrite_symbols
1101 #endif /* not KERNEL */
1102 )
1103 {
1104 kload_error result = kload_error_none;
1105
1106 int kld_result;
1107 int mach_result;
1108 struct mach_header * kld_header;
1109 const char * kmod_symbol = "_kmod_info";
1110 unsigned long kernel_kmod_info;
1111 kmod_info_t * local_kmod_info = NULL;
1112 char * dest_address = 0;
1113 #ifndef KERNEL
1114 char * allocated_filename = NULL;
1115 char * symbol_filename = NULL;
1116 int file_check;
1117 vm_address_t vm_buffer = 0;
1118 #endif /* not KERNEL */
1119
1120 /* A kernel component is by nature already linked and loaded and has
1121 * no work to be done upon it.
1122 */
1123 if (entry->is_kernel_component && !entry->is_symbol_set) {
1124 result = kload_error_none;
1125 goto finish;
1126 }
1127
1128 G_current_load_entry = entry;
1129
1130 if (log_level >= kload_log_level_load_basic) {
1131 #ifndef KERNEL
1132 if (do_load) {
1133 #endif /* not KERNEL */
1134 kload_log_message("link/loading file %s" KNL, entry->name);
1135 #ifndef KERNEL
1136 } else {
1137 kload_log_message("linking file %s" KNL, entry->name);
1138 }
1139 #endif /* not KERNEL */
1140 }
1141
1142 #ifndef KERNEL
1143 if (entry->link_output_file != entry->name) {
1144 symbol_filename = entry->link_output_file;
1145 }
1146
1147 if (symbol_filename) {
1148 file_check = kload_file_exists(symbol_filename);
1149 if (file_check < 0) {
1150 kload_log_error("error checking existence of file %s" KNL,
1151 symbol_filename);
1152 } else if (file_check > 0 && !overwrite_symbols) {
1153
1154 if (!ask_overwrite_symbols) {
1155 kload_log_message("symbol file %s exists; not overwriting" KNL,
1156 symbol_filename);
1157 symbol_filename = NULL;
1158 } else {
1159 int approve = (*__kload_approve_func)(1,
1160 "\nSymbol file %s exists; overwrite", symbol_filename);
1161
1162 if (approve < 0) {
1163 result = kload_error_unspecified;
1164 goto finish;
1165 } else if (approve == 0) {
1166 if (allocated_filename) free(allocated_filename);
1167 allocated_filename = NULL;
1168 symbol_filename = NULL;
1169 }
1170 }
1171 }
1172 }
1173
1174 if (symbol_filename &&
1175 (interactive_level ||
1176 log_level >= kload_log_level_basic) ) {
1177
1178 kload_log_message("writing symbol file %s" KNL, symbol_filename);
1179 }
1180
1181 if (do_load) {
1182 if (interactive_level && entry->loaded_address) {
1183 kload_log_message(
1184 "module %s is already loaded as %s at address 0x%08x" KNL,
1185 entry->name, entry->expected_kmod_name,
1186 entry->loaded_address);
1187 } else if ( (interactive_level == 1 && is_root) ||
1188 (interactive_level == 2) ) {
1189
1190 int approve = (*__kload_approve_func)(1,
1191 "\nLoad module %s", entry->name);
1192
1193 if (approve < 0) {
1194 result = kload_error_unspecified;
1195 goto finish;
1196 } else if (approve == 0) {
1197 result = kload_error_user_abort;
1198 goto finish;
1199 }
1200 }
1201 }
1202 #endif /* not KERNEL */
1203
1204 entry->object = kld_file_getaddr(entry->name, &entry->object_length);
1205 if (!entry->object) {
1206 kload_log_error("kld_file_getaddr() failed for module %s" KNL,
1207 entry->name);
1208 __kload_clear_kld_globals();
1209 result = kload_error_link_load;
1210 goto finish;
1211 }
1212
1213 if (entry->is_symbol_set) {
1214 entry->symbols = (vm_address_t) entry->object;
1215 entry->symbols_length = entry->object_length;
1216
1217 #ifndef KERNEL
1218 if (symbol_filename) {
1219 if (!_IOWriteBytesToFile(symbol_filename, (void *) entry->symbols, entry->symbols_length)) {
1220 kload_log_error("write symbol file failed for module %s" KNL,
1221 entry->name);
1222 __kload_clear_kld_globals();
1223 result = kload_error_link_load;
1224 goto finish;
1225 }
1226 symbol_filename = 0;
1227 if (G_prelink && (entry->name != entry->link_output_file))
1228 {
1229 kload_log_error("prelink %s %s %s" KNL,
1230 entry->name, entry->link_output_file, entry->expected_kmod_name);
1231 register_prelink(entry, NULL, NULL);
1232 }
1233 }
1234 #endif /* not KERNEL */
1235 if (entry->opaques) {
1236 result = kload_error_none;
1237 goto finish;
1238 }
1239 }
1240
1241 #ifndef KERNEL
1242 kld_result = kld_load_from_memory(&kld_header, entry->name,
1243 entry->object, entry->object_length, symbol_filename);
1244 #else
1245 kld_result = kld_load_from_memory(&kld_header, entry->name,
1246 entry->object, entry->object_length);
1247 #endif /* not KERNEL */
1248
1249 #ifndef KERNEL
1250 fflush(stdout);
1251 fflush(stderr);
1252 #endif /* not KERNEL */
1253
1254 dgraph->have_loaded_symbols = true;
1255
1256 if (!kld_result || !entry->kernel_load_address) {
1257 kload_log_error("kld_load_from_memory() failed for module %s" KNL,
1258 entry->name);
1259 __kload_clear_kld_globals();
1260 entry->need_cleanup = 1;
1261 result = kload_error_link_load;
1262 goto finish;
1263 }
1264
1265 if (entry->is_symbol_set) {
1266 result = kload_error_none;
1267 goto finish;
1268 }
1269
1270 entry->linked_image = kld_header;
1271 entry->linked_image_length = -1; // unknown!
1272
1273 /* If we're in the kernel and not loading (as when handling an
1274 * already-loaded dependency), we don't need to waste any CPU
1275 * cycles looking up the kmod_info struct.
1276 */
1277 #ifdef KERNEL
1278 if (entry->do_load) {
1279 #endif /* KERNEL */
1280
1281 kld_result = kld_lookup(kmod_symbol, &kernel_kmod_info);
1282 if (!kld_result) {
1283 kload_log_error("kld_lookup(\"%s\") failed for module %s" KNL,
1284 kmod_symbol, entry->name);
1285 entry->need_cleanup = 1;
1286 result = kload_error_link_load;
1287 goto finish;
1288 }
1289
1290 #ifdef KERNEL
1291 }
1292 #endif /* KERNEL */
1293
1294 kld_result = kld_forget_symbol(kmod_symbol);
1295 #ifndef KERNEL
1296 fflush(stdout);
1297 fflush(stderr);
1298 #endif /* not KERNEL */
1299 if (!kld_result) {
1300 kload_log_error("kld_forget_symbol(\"%s\") failed for module %s" KNL,
1301 kmod_symbol, entry->name);
1302 entry->need_cleanup = 1;
1303 result = kload_error_link_load;
1304 goto finish;
1305 }
1306
1307 /* This section is always done in userland, but in kernel space
1308 * only if we're loading the kext, because what we have in kernel
1309 * space for an already-loaded kext is the kext itself, which
1310 * must not be touched again after it's been loaded and started.
1311 */
1312 #ifdef KERNEL
1313 if (entry->do_load)
1314 #endif /* KERNEL */
1315 {
1316
1317
1318 /* Get the linked image's kmod_info by translating from the
1319 * destined kernel-space address at kernel_kmod_info to an
1320 * offset from kld_header.
1321 */
1322 local_kmod_info = (kmod_info_t *)((unsigned long)kernel_kmod_info -
1323 (unsigned long)G_current_load_entry->kernel_load_address +
1324 (unsigned long)kld_header);
1325
1326 /* Stamp the bundle ID and version from the entry over anything
1327 * resident inside the kmod.
1328 */
1329 bzero(local_kmod_info->name, sizeof(local_kmod_info->name));
1330 strcpy(local_kmod_info->name, entry->expected_kmod_name);
1331
1332 bzero(local_kmod_info->version, sizeof(local_kmod_info->version));
1333 strcpy(local_kmod_info->version, entry->expected_kmod_vers);
1334
1335 if (log_level >= kload_log_level_details) {
1336 kload_log_message("kmod name: %s" KNL, local_kmod_info->name);
1337 kload_log_message("kmod start @ 0x%x (offset 0x%lx)" KNL,
1338 (vm_address_t)local_kmod_info->start,
1339 (unsigned long)local_kmod_info->start - (unsigned long)G_current_load_entry->kernel_load_address);
1340 kload_log_message("kmod stop @ 0x%x (offset 0x%lx)" KNL,
1341 (vm_address_t)local_kmod_info->stop,
1342 (unsigned long)local_kmod_info->stop - (unsigned long)G_current_load_entry->kernel_load_address);
1343 }
1344
1345 if (!local_kmod_info->start || !local_kmod_info->start) {
1346 kload_log_error(
1347 "error for module file %s; start or stop address is zero" KNL,
1348 entry->name);
1349 entry->need_cleanup = 1;
1350 result = kload_error_link_load;
1351 goto finish;
1352 }
1353
1354 /* Record link info into kmod_info struct, rounding the hdr_size
1355 * to fit the adjustment that was made in __kload_linkedit_address().
1356 */
1357 if (entry->kernel_alloc_address) {
1358 local_kmod_info->address = entry->kernel_alloc_address;
1359 } else {
1360 local_kmod_info->address = entry->loaded_address;
1361 }
1362 local_kmod_info->size = entry->kernel_alloc_size;
1363 local_kmod_info->hdr_size = round_page(entry->kernel_hdr_size);
1364
1365 }
1366
1367 #ifndef KERNEL
1368 if (G_prelink && (entry->name != entry->link_output_file))
1369 {
1370 register_prelink(entry, local_kmod_info, kernel_kmod_info);
1371 }
1372
1373 if (do_load && entry->do_load) {
1374 mach_result = vm_allocate(mach_task_self(), &vm_buffer,
1375 entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
1376 if (mach_result != KERN_SUCCESS) {
1377 kload_log_error("unable to vm_allocate() copy buffer" KNL);
1378 entry->need_cleanup = 1;
1379 result = kload_error_no_memory; // FIXME: kernel error?
1380 goto finish;
1381 }
1382
1383 dest_address = (char *)vm_buffer;
1384
1385 memcpy(dest_address, kld_header, entry->kernel_hdr_size);
1386 memcpy(dest_address + round_page(entry->kernel_hdr_size),
1387 (void *)((unsigned long)kld_header + entry->kernel_hdr_size),
1388 entry->kernel_load_size - entry->kernel_hdr_size);
1389
1390 mach_result = vm_write(G_kernel_port, entry->kernel_alloc_address,
1391 vm_buffer, entry->kernel_alloc_size);
1392 if (mach_result != KERN_SUCCESS) {
1393 kload_log_error("unable to write module to kernel memory" KNL);
1394 entry->need_cleanup = 1;
1395 result = kload_error_kernel_error;
1396 goto finish;
1397 }
1398
1399 mach_result = kmod_create(G_kernel_priv_port,
1400 (vm_address_t)kernel_kmod_info, &(entry->kmod_id));
1401
1402 #else
1403 if (entry->do_load) {
1404 dest_address = (char *)entry->kernel_alloc_address;
1405 memcpy(dest_address, kld_header, entry->kernel_hdr_size);
1406 memcpy(dest_address + round_page(entry->kernel_hdr_size),
1407 (void *)((unsigned long)kld_header + entry->kernel_hdr_size),
1408 entry->kernel_load_size - entry->kernel_hdr_size);
1409
1410 /* We've written data & instructions into kernel memory, so flush
1411 * the data cache and invalidate the instruction cache.
1412 */
1413 flush_dcache(entry->kernel_alloc_address, entry->kernel_alloc_size, false);
1414 invalidate_icache(entry->kernel_alloc_address, entry->kernel_alloc_size, false);
1415
1416 mach_result = kmod_create_internal(
1417 (kmod_info_t *)kernel_kmod_info, &(entry->kmod_id));
1418
1419 #endif /* not KERNEL */
1420
1421 if (mach_result != KERN_SUCCESS) {
1422 kload_log_error("unable to register module with kernel" KNL);
1423 entry->need_cleanup = 1;
1424 result = kload_error_kernel_error;
1425 goto finish;
1426 }
1427
1428 #ifndef KERNEL
1429 if (interactive_level || log_level >= kload_log_level_load_basic) {
1430 #else
1431 if (log_level >= kload_log_level_load_basic) {
1432 #endif /* not KERNEL */
1433 kload_log_message(
1434 "module %s created as # %d at address 0x%x, size %ld" KNL,
1435 entry->expected_kmod_name, entry->kmod_id,
1436 entry->kernel_alloc_address,
1437 entry->kernel_alloc_size);
1438
1439 #ifndef KERNEL
1440 }
1441 #else
1442 }
1443 #endif /* not KERNEL */
1444
1445 #ifndef KERNEL
1446 if (interactive_level) {
1447 kload_log_message(
1448 "You can now break to the debugger and set breakpoints "
1449 " for this extension." KNL);
1450 }
1451 #endif /* not KERNEL */
1452
1453 #ifndef KERNEL
1454 }
1455 #else
1456 }
1457 #endif /* not KERNEL */
1458
1459 finish:
1460
1461 #ifndef KERNEL
1462 if (allocated_filename) {
1463 free(allocated_filename);
1464 }
1465 if (vm_buffer) {
1466 vm_deallocate(mach_task_self(), vm_buffer, entry->kernel_alloc_size);
1467 }
1468 #endif /* not KERNEL */
1469 __kload_clear_kld_globals();
1470
1471 return result;
1472 }
1473
1474 /*******************************************************************************
1475 *******************************************************************************/
1476
1477 #ifndef KERNEL
1478 static kload_error
1479 register_prelink(dgraph_entry_t * entry,
1480 kmod_info_t * local_kmod_info, vm_offset_t kernel_kmod_info)
1481 {
1482 CFIndex i, j, depoffset;
1483 Boolean exists;
1484 kmod_info_t desc;
1485
1486 depoffset = CFDataGetLength(G_prelink_dependencies) / sizeof(CFIndex);
1487
1488 for (i = 0; i < entry->num_dependencies; i++)
1489 {
1490 exists = false;
1491 for (j = 1; (j < (1 + G_prelink->modules[0].id)); j++)
1492 {
1493 exists = (0 == strcmp(entry->dependencies[i]->expected_kmod_name,
1494 G_prelink->modules[j].name));
1495 if (exists)
1496 break;
1497 }
1498 if (!exists)
1499 {
1500 bzero(&desc, sizeof(desc));
1501 strcpy(desc.name, entry->dependencies[i]->expected_kmod_name);
1502
1503 if (log_level >= kload_log_level_basic) {
1504 kload_log_message("[%d] (dep)\n %s" KNL,
1505 G_prelink->modules[0].id + 1, desc.name);
1506 }
1507 G_prelink->modules[0].id++;
1508 CFDataAppendBytes(G_prelink_data, (UInt8 *) &desc, sizeof(desc));
1509 G_prelink = (struct PrelinkState *) CFDataGetMutableBytePtr(G_prelink_data);
1510 }
1511
1512 G_prelink->modules[0].reference_count++;
1513 OSWriteBigInt32(&j, 0, j);
1514 CFDataAppendBytes(G_prelink_dependencies, (UInt8 *) &j, sizeof(j));
1515 }
1516 if (log_level >= kload_log_level_basic) {
1517 kload_log_message("[%d] 0x%08x info 0x%08x\n %s,\n %s" KNL,
1518 G_prelink->modules[0].id + 1, entry->kernel_load_address,
1519 kernel_kmod_info, entry->link_output_file, entry->name);
1520 }
1521
1522 if (local_kmod_info)
1523 desc = *local_kmod_info;
1524 else
1525 {
1526 bzero(&desc, sizeof(desc));
1527 desc.size = entry->symbols_length;
1528 }
1529
1530 desc.id = kernel_kmod_info;
1531 desc.reference_count = entry->num_dependencies;
1532 desc.reference_list = (kmod_reference_t *) depoffset;
1533
1534 /* Stamp the bundle ID and version from the entry over anything
1535 * resident inside the kmod.
1536 */
1537 bzero(desc.name, sizeof(local_kmod_info->name));
1538 strcpy(desc.name, entry->expected_kmod_name);
1539 bzero(desc.version, sizeof(local_kmod_info->version));
1540 strcpy(desc.version, entry->expected_kmod_vers);
1541
1542 G_prelink->modules[0].id++;
1543 CFDataAppendBytes(G_prelink_data, (UInt8 *) &desc, sizeof(desc));
1544 G_prelink = (struct PrelinkState *) CFDataGetMutableBytePtr(G_prelink_data);
1545
1546 return kload_error_none;
1547 }
1548
1549 #endif
1550
1551 /*******************************************************************************
1552 *
1553 *******************************************************************************/
1554 PRIV_EXT
1555 #ifndef KERNEL
1556 kload_error kload_map_dgraph(
1557 dgraph_t * dgraph,
1558 const char * kernel_file)
1559 #else
1560 kload_error kload_map_dgraph(
1561 dgraph_t * dgraph)
1562 #endif /* not KERNEL */
1563 {
1564 kload_error result = kload_error_none;
1565 unsigned int i;
1566
1567 if (log_level >= kload_log_level_load_details) {
1568 #ifndef KERNEL
1569 kload_log_message("mapping the kernel file %s" KNL, kernel_file);
1570 #else
1571 kload_log_message("mapping the kernel" KNL);
1572 #endif /* not KERNEL */
1573 }
1574
1575 #ifndef KERNEL
1576 if (!kld_file_map(kernel_file)) {
1577 result = kload_error_link_load;
1578 goto finish;
1579 }
1580 #endif /* not KERNEL */
1581
1582 for (i = 0; i < dgraph->length; i++) {
1583 dgraph_entry_t * entry = dgraph->load_order[i];
1584
1585 if (entry->is_kernel_component && !entry->is_symbol_set) {
1586 continue;
1587 }
1588
1589 result = kload_map_entry(entry);
1590 if (result != kload_error_none) {
1591 goto finish;
1592 }
1593 }
1594
1595 finish:
1596 return result;
1597
1598 }
1599
1600 /*******************************************************************************
1601 *
1602 *******************************************************************************/
1603 PRIV_EXT
1604 kload_error kload_map_entry(dgraph_entry_t * entry)
1605 {
1606 kload_error result = kload_error_none;
1607
1608 if (entry->is_kernel_component && !entry->is_symbol_set) {
1609 kload_log_error("attempt to map kernel component %s" KNL, entry->name);
1610 result = kload_error_invalid_argument;
1611 goto finish;
1612 }
1613
1614 if (log_level >= kload_log_level_load_details) {
1615 kload_log_message("mapping module file %s" KNL, entry->name);
1616 }
1617
1618 if (kld_file_getaddr(entry->name, NULL)) {
1619 if (log_level >= kload_log_level_load_details) {
1620 kload_log_message("module file %s is already mapped" KNL, entry->name);
1621 }
1622 result = kload_error_none;
1623 goto finish;
1624 }
1625
1626 #ifndef KERNEL
1627 if (!kld_file_map(entry->name)) {
1628 #else
1629 if (!kld_file_map(entry->name, entry->object, entry->object_length,
1630 entry->object_is_kmem)) {
1631 #endif /* not KERNEL */
1632 kload_log_error("error mapping module file %s" KNL, entry->name);
1633
1634 result = kload_error_link_load;
1635 goto finish;
1636 #ifndef KERNEL
1637 }
1638 #else
1639 }
1640 #endif /* not KERNEL */
1641
1642 entry->is_mapped = true;
1643
1644 /* Clear these bits now, as the kld patch module now owns the info
1645 * and it is subject to change. We reset them in the entry from the
1646 * kld patch module as needed.
1647 */
1648 entry->object = 0;
1649 entry->object_length = 0;
1650 #ifdef KERNEL
1651 entry->object_is_kmem = false;
1652 #endif /* KERNEL */
1653
1654 // FIXME: Stop using this symbol; have the info passed in by
1655 // FIXME: ...the kext management library.
1656 #ifndef KERNEL
1657 if (!entry->is_kernel_component && !kld_file_lookupsymbol(entry->name, "_kmod_info")) {
1658 kload_log_error("%s does not not contain kernel extension code" KNL,
1659 entry->name);
1660 result = kload_error_executable_bad;
1661 goto finish;
1662 }
1663 #endif /* not KERNEL */
1664
1665 finish:
1666 return result;
1667 }
1668
1669 #ifndef KERNEL
1670 /*******************************************************************************
1671 *
1672 *******************************************************************************/
1673 kload_error kload_request_load_addresses(
1674 dgraph_t * dgraph,
1675 const char * kernel_file)
1676 {
1677 kload_error result = kload_error_none;
1678 int i;
1679 const char * user_response = NULL; // must free
1680 int scan_result;
1681 unsigned int address;
1682
1683 /* We have to map all object files to get their CFBundleIdentifier
1684 * names.
1685 */
1686 result = kload_map_dgraph(dgraph, kernel_file);
1687 if (result != kload_error_none) {
1688 kload_log_error("error mapping object files" KNL);
1689 goto finish;
1690 }
1691
1692 // fixme: this shouldn't be printf, should it?
1693 printf("enter the hexadecimal load addresses for these modules:\n");
1694
1695 for (i = 0; i < dgraph->length; i++) {
1696 dgraph_entry_t * entry = dgraph->load_order[i];
1697
1698 if (!entry) {
1699 result = kload_error_unspecified;
1700 goto finish;
1701 }
1702
1703 if (entry->is_kernel_component) {
1704 continue;
1705 }
1706
1707 if (!entry->is_mapped) {
1708 result = kload_error_unspecified;
1709 goto finish;
1710 }
1711
1712 user_response = __kload_input_func("%s:",
1713 entry->expected_kmod_name);
1714 if (!user_response) {
1715 result = kload_error_unspecified;
1716 goto finish;
1717 }
1718 scan_result = sscanf(user_response, "%x", &address);
1719 if (scan_result < 1 || scan_result == EOF) {
1720 result = kload_error_unspecified;
1721 goto finish;
1722 }
1723 entry->loaded_address = address;
1724 }
1725
1726 finish:
1727 return result;
1728
1729 }
1730
1731 /*******************************************************************************
1732 * addresses is a NULL-terminated list of string of the form "module_id@address"
1733 *******************************************************************************/
1734 kload_error kload_set_load_addresses_from_args(
1735 dgraph_t * dgraph,
1736 const char * kernel_file,
1737 char ** addresses)
1738 {
1739 kload_error result = kload_error_none;
1740 int i, j;
1741
1742
1743 /* We have to map all object files to get their CFBundleIdentifier
1744 * names.
1745 */
1746 result = kload_map_dgraph(dgraph, kernel_file);
1747 if (result != kload_error_none) {
1748 kload_log_error("error mapping object files" KNL);
1749 goto finish;
1750 }
1751
1752 /*****
1753 * Run through and assign all addresses to their relevant module
1754 * entries.
1755 */
1756 for (i = 0; i < dgraph->length; i++) {
1757 dgraph_entry_t * entry = dgraph->load_order[i];
1758
1759 if (!entry) {
1760 result = kload_error_unspecified;
1761 goto finish;
1762 }
1763
1764 if (entry->is_kernel_component) {
1765 continue;
1766 }
1767
1768 if (!entry->is_mapped) {
1769 result = kload_error_unspecified;
1770 goto finish;
1771 }
1772
1773 for (j = 0; addresses[j]; j++) {
1774 char * this_addr = addresses[j];
1775 char * address_string = NULL;
1776 unsigned int address;
1777 unsigned int module_namelen = strlen(entry->expected_kmod_name);
1778
1779 if (!this_addr) {
1780 result = kload_error_unspecified;
1781 goto finish;
1782 }
1783
1784 if (strncmp(this_addr, entry->expected_kmod_name, module_namelen)) {
1785 continue;
1786 }
1787 if (this_addr[module_namelen] != '@') {
1788 continue;
1789 }
1790
1791 address_string = index(this_addr, '@');
1792 if (!address_string) {
1793 result = kload_error_unspecified;
1794 goto finish;
1795 }
1796 address_string++;
1797 address = strtoul(address_string, NULL, 16);
1798 entry->loaded_address = address;
1799 }
1800 }
1801
1802 /*****
1803 * Now that we've done that see that all non-kernel modules do have
1804 * addresses set. If even one doesn't, we can't complete the link
1805 * relocation of symbols, so return a usage error.
1806 */
1807 for (i = 0; i < dgraph->length; i++) {
1808 dgraph_entry_t * entry = dgraph->load_order[i];
1809
1810 if (entry->is_kernel_component) {
1811 continue;
1812 }
1813
1814 if (!entry->loaded_address) {
1815 result = kload_error_invalid_argument;
1816 goto finish;
1817 }
1818 }
1819
1820 finish:
1821 return result;
1822
1823 }
1824
1825 /*******************************************************************************
1826 * This function requires G_kernel_priv_port to be set before it will work.
1827 *******************************************************************************/
1828 kload_error kload_set_load_addresses_from_kernel(
1829 dgraph_t * dgraph,
1830 const char * kernel_file,
1831 int do_load)
1832 {
1833 kload_error result = kload_error_none;
1834 int mach_result;
1835 kmod_info_t * loaded_modules = NULL;
1836 int loaded_bytecount = 0;
1837 unsigned int i;
1838
1839
1840 /*****
1841 * We have to map the dgraph's modules before checking whether they've
1842 * been loaded.
1843 */
1844 result = kload_map_dgraph(dgraph, kernel_file);
1845 if (result != kload_error_none) {
1846 kload_log_error("can't map module files" KNL);
1847 goto finish;
1848 }
1849
1850
1851 /* First clear all the load addresses.
1852 */
1853 for (i = 0; i < dgraph->length; i++) {
1854 struct dgraph_entry_t * entry = dgraph->load_order[i];
1855 entry->loaded_address = 0;
1856 }
1857
1858 mach_result = kmod_get_info(G_kernel_priv_port,
1859 (void *)&loaded_modules, &loaded_bytecount);
1860 if (mach_result != KERN_SUCCESS) {
1861 kload_log_error("kmod_get_info() failed" KNL);
1862 result = kload_error_kernel_error;
1863 goto finish;
1864 }
1865
1866 /*****
1867 * Find out which modules have already been loaded & verify
1868 * that loaded versions are same as requested.
1869 */
1870 for (i = 0; i < dgraph->length; i++) {
1871 kload_error cresult;
1872 dgraph_entry_t * current_entry = dgraph->load_order[i];
1873
1874 /* If necessary, check whether the current module is already loaded.
1875 * (We already did the root module above.)
1876 */
1877 cresult = __kload_check_module_loaded(dgraph, current_entry,
1878 loaded_modules, do_load);
1879 if ( ! (cresult == kload_error_none ||
1880 cresult == kload_error_already_loaded) ) {
1881 goto finish;
1882 }
1883 if (current_entry == dgraph->root &&
1884 cresult == kload_error_already_loaded) {
1885
1886 result = cresult;
1887 }
1888 }
1889
1890 finish:
1891
1892 if (loaded_modules) {
1893 vm_deallocate(mach_task_self(), (vm_address_t)loaded_modules,
1894 loaded_bytecount);
1895 loaded_modules = 0;
1896 }
1897
1898 return result;
1899 }
1900
1901 #else
1902 /*******************************************************************************
1903 *
1904 *******************************************************************************/
1905 PRIV_EXT
1906 kload_error kload_set_load_addresses_from_kernel(
1907 dgraph_t * dgraph)
1908 {
1909 kload_error result = kload_error_none;
1910 #ifndef KERNEL
1911 int mach_result;
1912 kmod_info_t * loaded_modules = NULL;
1913 int loaded_bytecount = 0;
1914 #endif /* not KERNEL */
1915 unsigned int i;
1916
1917
1918 /*****
1919 * We have to map the dgraph's modules before checking whether they've
1920 * been loaded.
1921 */
1922 result = kload_map_dgraph(dgraph);
1923 if (result != kload_error_none) {
1924 kload_log_error("can't map module files" KNL);
1925 goto finish;
1926 }
1927
1928
1929 /* First clear all the load addresses.
1930 */
1931 for (i = 0; i < dgraph->length; i++) {
1932 struct dgraph_entry_t * entry = dgraph->load_order[i];
1933 entry->loaded_address = 0;
1934 }
1935
1936 /*****
1937 * Find out which modules have already been loaded & verify
1938 * that loaded versions are same as requested.
1939 */
1940 for (i = 0; i < dgraph->length; i++) {
1941 kload_error cresult;
1942 dgraph_entry_t * current_entry = dgraph->load_order[i];
1943
1944 /* If necessary, check whether the current module is already loaded.
1945 * (We already did the root module above.)
1946 */
1947 cresult = __kload_check_module_loaded(dgraph, current_entry, false);
1948 if ( ! (cresult == kload_error_none ||
1949 cresult == kload_error_already_loaded) ) {
1950 goto finish;
1951 }
1952 if (current_entry == dgraph->root &&
1953 cresult == kload_error_already_loaded) {
1954
1955 result = cresult;
1956 }
1957 }
1958
1959 finish:
1960
1961 return result;
1962 }
1963 #endif /* not KERNEL */
1964
1965 /*******************************************************************************
1966 *
1967 *******************************************************************************/
1968 #ifdef KERNEL
1969 extern kern_return_t kmod_load_from_cache(const char * kmod_name);
1970 #endif /* KERNEL */
1971
1972 static kmod_info_t * __kload_find_kmod_info(const char * kmod_name
1973 #ifndef KERNEL
1974 ,
1975 kmod_info_t * kmod_list
1976 #endif /* not KERNEL */
1977 )
1978 {
1979 #ifndef KERNEL
1980 unsigned int i;
1981
1982 for (i = 0; ; i++) {
1983 kmod_info_t * current_kmod = &(kmod_list[i]);
1984 if (0 == strcmp(current_kmod->name, kmod_name)) {
1985 return current_kmod;
1986 }
1987 if (kmod_list[i].next == 0) {
1988 break;
1989 }
1990 }
1991 return NULL;
1992 #else
1993 kmod_info_t * info;
1994 info = kmod_lookupbyname_locked(kmod_name);
1995 if (!info && (KERN_SUCCESS == kmod_load_from_cache(kmod_name))) {
1996 info = kmod_lookupbyname_locked(kmod_name);
1997 }
1998 return info;
1999 #endif /* not KERNEL */
2000 }
2001
2002 /*******************************************************************************
2003 *
2004 *******************************************************************************/
2005 static
2006 kload_error __kload_check_module_loaded(
2007 dgraph_t * dgraph,
2008 dgraph_entry_t * entry,
2009 #ifndef KERNEL
2010 kmod_info_t * kmod_list,
2011 #endif /* not KERNEL */
2012 int log_if_already)
2013 {
2014 kload_error result = kload_error_none;
2015 const char * kmod_name;
2016 kmod_info_t * current_kmod = 0;
2017
2018 VERS_version entry_vers;
2019 VERS_version loaded_vers;
2020
2021 if (false && entry->is_kernel_component) {
2022 kmod_name = entry->name;
2023 } else {
2024 kmod_name = entry->expected_kmod_name;
2025 if (log_level >= kload_log_level_load_details) {
2026 kload_log_message("checking whether module file %s is already loaded" KNL,
2027 kmod_name);
2028 }
2029 }
2030
2031 #ifndef KERNEL
2032 current_kmod = __kload_find_kmod_info(kmod_name, kmod_list);
2033 #else
2034 current_kmod = __kload_find_kmod_info(kmod_name);
2035 #endif /* not KERNEL */
2036
2037 if (!current_kmod) {
2038 goto finish;
2039 }
2040
2041 entry->do_load = 0;
2042 entry->kmod_id = current_kmod->id;
2043 entry->loaded_address = current_kmod->address;
2044
2045 if (entry->is_kernel_component) {
2046 goto finish;
2047 }
2048
2049 if (log_level >= kload_log_level_load_details) {
2050 kload_log_message("module file %s is loaded; checking status" KNL,
2051 kmod_name);
2052 }
2053
2054 // We really want to move away from having this info in a kmod....
2055 //
2056 loaded_vers = VERS_parse_string(current_kmod->version);
2057 if (loaded_vers < 0) {
2058 kload_log_error(
2059 "can't parse version string \"%s\" of loaded module %s" KNL,
2060 current_kmod->version,
2061 current_kmod->name);
2062 result = kload_error_unspecified;
2063 goto finish;
2064 }
2065
2066 entry_vers = VERS_parse_string(entry->expected_kmod_vers);
2067 if (entry_vers < 0) {
2068 kload_log_error(
2069 "can't parse version string \"%s\" of module file %s" KNL,
2070 entry->expected_kmod_name,
2071 kmod_name);
2072 result = kload_error_unspecified;
2073 goto finish;
2074 }
2075
2076 if (loaded_vers != entry_vers) {
2077 kload_log_error(
2078 "loaded version %s of module %s differs from "
2079 "requested version %s" KNL,
2080 current_kmod->version,
2081 current_kmod->name,
2082 entry->expected_kmod_name);
2083 if (entry == dgraph->root) {
2084 result = kload_error_loaded_version_differs;
2085 } else {
2086 result = kload_error_dependency_loaded_version_differs;
2087 }
2088 goto finish;
2089 } else {
2090
2091 if (log_if_already && log_level >=
2092 kload_log_level_load_basic) {
2093
2094 kload_log_message(
2095 "module %s (identifier %s) is already loaded" KNL,
2096 entry->name, kmod_name);
2097 }
2098 result = kload_error_already_loaded;
2099 goto finish;
2100 }
2101
2102 finish:
2103 #ifdef KERNEL
2104 // Do this ONLY if in the kernel!
2105 if (current_kmod) {
2106 kfree(current_kmod, sizeof(kmod_info_t));
2107 }
2108 #endif /* KERNEL */
2109 return result;
2110 }
2111
2112 /*******************************************************************************
2113 *
2114 *******************************************************************************/
2115 PRIV_EXT
2116 kload_error __kload_patch_dgraph(dgraph_t * dgraph
2117 #ifndef KERNEL
2118 ,
2119 const char * kernel_file
2120 #endif /* not KERNEL */
2121 )
2122 {
2123 kload_error result = kload_error_none;
2124 unsigned int i;
2125
2126 #ifndef KERNEL
2127 if (!kld_file_merge_OSObjects(kernel_file)) {
2128 result = kload_error_link_load;
2129 goto finish;
2130 }
2131 #endif /* not KERNEL */
2132
2133 for (i = 0; i < dgraph->length; i++) {
2134 dgraph_entry_t * current_entry = dgraph->load_order[i];
2135
2136 /* The kernel has already been patched.
2137 */
2138 if (current_entry->is_kernel_component) {
2139 continue;
2140 }
2141
2142 if (log_level >= kload_log_level_load_details) {
2143 kload_log_message("patching C++ code in module %s" KNL,
2144 current_entry->name);
2145 }
2146
2147 #ifndef KERNEL
2148 /* In userland, we call the patch function for all kmods,
2149 * loaded or not, because we don't have all the info that
2150 * the kernel environment has.
2151 */
2152 if (!kld_file_patch_OSObjects(current_entry->name)) {
2153 result = kload_error_link_load; // FIXME: need a "patch" error?
2154 goto finish;
2155 }
2156 #else
2157 /* In the kernel, we call the merge function for already-loaded
2158 * kmods, since the kld patch environment retains info for kmods
2159 * that have already been patched. The patch function does a little
2160 * more work, and is only for kmods that haven't been processed yet.
2161 * NOTE: We are depending here on kload_check_module_loaded()
2162 * having been called, which is guaranteed by kload_load_dgraph()
2163 * is used, but not by its subroutines (such as
2164 * __kload_load_modules()).
2165 */
2166 if (current_entry->loaded_address) {
2167 if (!kld_file_merge_OSObjects(current_entry->name)) {
2168 result = kload_error_link_load; // FIXME: need a "patch" error?
2169 goto finish;
2170 }
2171 } else {
2172 if (!kld_file_patch_OSObjects(current_entry->name)) {
2173 result = kload_error_link_load; // FIXME: need a "patch" error?
2174 goto finish;
2175 }
2176 }
2177 #endif /* not KERNEL */
2178
2179 }
2180
2181 if (!kld_file_prepare_for_link()) {
2182 result = kload_error_link_load; // FIXME: need more specific error?
2183 goto finish;
2184 }
2185
2186 finish:
2187 return result;
2188 }
2189
2190 #ifndef KERNEL
2191 /*******************************************************************************
2192 *
2193 *******************************************************************************/
2194 #define __KLOAD_PATCH_EXTENSION ".patch"
2195
2196 kload_error __kload_output_patches(
2197 dgraph_t * dgraph,
2198 const char * patch_file,
2199 const char * patch_dir,
2200 int ask_overwrite_symbols,
2201 int overwrite_symbols)
2202 {
2203 kload_error result = kload_error_none;
2204 unsigned int i;
2205 char * allocated_filename = NULL;
2206 char * patch_filename = NULL;
2207 int file_check;
2208 int output_patch;
2209
2210 if (patch_dir) {
2211
2212 for (i = 0; i < dgraph->length; i++) {
2213
2214 struct dgraph_entry_t * entry = dgraph->load_order[i];
2215 unsigned long length;
2216
2217 if (entry->is_kernel_component) {
2218 continue;
2219 }
2220
2221 length = strlen(patch_dir) +
2222 strlen(entry->expected_kmod_name) +
2223 strlen(__KLOAD_PATCH_EXTENSION) +
2224 1 + 1 ; // 1 for '/' added, 1 for terminating null
2225 if (length >= MAXPATHLEN) {
2226 kload_log_error(
2227 "output filename \"%s/%s%s\" would be too long" KNL,
2228 patch_dir, entry->expected_kmod_name,
2229 __KLOAD_PATCH_EXTENSION);
2230 result = kload_error_invalid_argument;
2231 goto finish;
2232 }
2233
2234 allocated_filename = (char *)malloc(length);
2235 if (! allocated_filename) {
2236 kload_log_error("malloc failure" KNL);
2237 result = kload_error_no_memory;
2238 goto finish;
2239 }
2240
2241 patch_filename = allocated_filename;
2242 strcpy(patch_filename, patch_dir);
2243 strcat(patch_filename, "/");
2244 strcat(patch_filename, entry->expected_kmod_name);
2245 strcat(patch_filename, __KLOAD_PATCH_EXTENSION);
2246
2247 output_patch = 1;
2248 file_check = kload_file_exists(patch_filename);
2249
2250 if (file_check < 0) {
2251 kload_log_error("error checking existence of file %s" KNL,
2252 patch_filename);
2253 } else if (file_check > 0 && !overwrite_symbols) {
2254 if (!ask_overwrite_symbols) {
2255 kload_log_error(
2256 "patch file %s exists; not overwriting" KNL,
2257 patch_filename);
2258 output_patch = 0;
2259 } else {
2260 int approve = (*__kload_approve_func)(1,
2261 "\nPatch file %s exists; overwrite", patch_filename);
2262
2263 if (approve < 0) {
2264 result = kload_error_unspecified;
2265 goto finish;
2266 } else {
2267 output_patch = approve;
2268 }
2269 }
2270 }
2271
2272 if (output_patch) {
2273 if (log_level >= kload_log_level_basic) {
2274 kload_log_message("writing patch file %s" KNL, patch_filename);
2275 }
2276 kld_file_debug_dump(entry->name, patch_filename);
2277 }
2278
2279 if (allocated_filename) free(allocated_filename);
2280 allocated_filename = NULL;
2281 }
2282
2283 } else if (patch_file) {
2284 output_patch = 1;
2285 file_check = kload_file_exists(patch_file);
2286
2287 if (file_check < 0) {
2288 kload_log_error("error checking existence of file %s" KNL,
2289 patch_file);
2290 } else if (file_check > 0 && !overwrite_symbols) {
2291 if (!ask_overwrite_symbols) {
2292 kload_log_error("patch file %s exists; not overwriting" KNL,
2293 patch_filename);
2294 output_patch = 0;
2295 } else {
2296 int approve = (*__kload_approve_func)(1,
2297 "\nPatch file %s exists; overwrite", patch_filename);
2298
2299 if (approve < 0) {
2300 result = kload_error_unspecified;
2301 goto finish;
2302 } else {
2303 output_patch = approve;
2304 }
2305 }
2306 }
2307
2308 if (output_patch) {
2309 if (log_level >= kload_log_level_basic) {
2310 kload_log_message("writing patch file %s" KNL, patch_filename);
2311 }
2312 kld_file_debug_dump(dgraph->root->name, patch_file);
2313 }
2314 }
2315
2316 finish:
2317 if (allocated_filename) free(allocated_filename);
2318
2319 return result;
2320 }
2321 #endif /* not KERNEL */
2322
2323 /*******************************************************************************
2324 *
2325 *******************************************************************************/
2326 PRIV_EXT
2327 kload_error __kload_set_module_dependencies(dgraph_entry_t * entry) {
2328 kload_error result = kload_error_none;
2329 int mach_result;
2330 #ifndef KERNEL
2331 void * kmod_control_args = 0;
2332 int num_args = 0;
2333 #endif /* not KERNEL */
2334 kmod_t packed_id;
2335 unsigned int i;
2336 dgraph_entry_t * current_dep = NULL;
2337
2338 if (!entry->do_load) {
2339 result = kload_error_already_loaded;
2340 goto finish;
2341 }
2342
2343 for (i = 0; i < entry->num_dependencies; i++) {
2344 current_dep = entry->dependencies[i];
2345
2346 if (log_level >= kload_log_level_load_details) {
2347 kload_log_message("adding reference from %s (%d) to %s (%d)" KNL,
2348 entry->expected_kmod_name, entry->kmod_id,
2349 current_dep->expected_kmod_name, current_dep->kmod_id);
2350 }
2351
2352 packed_id = KMOD_PACK_IDS(entry->kmod_id, current_dep->kmod_id);
2353 #ifndef KERNEL
2354 mach_result = kmod_control(G_kernel_priv_port,
2355 packed_id, KMOD_CNTL_RETAIN, &kmod_control_args, &num_args);
2356 #else
2357 mach_result = kmod_retain(packed_id);
2358 #endif /* not KERNEL */
2359 if (mach_result != KERN_SUCCESS) {
2360 kload_log_error(
2361 "kmod retain failed for %s; destroying kmod" KNL,
2362 entry->expected_kmod_name);
2363 #ifndef KERNEL
2364 mach_result = kmod_destroy(G_kernel_priv_port, entry->kmod_id);
2365 #else
2366 mach_result = kmod_destroy_internal(entry->kmod_id);
2367 #endif /* not KERNEL */
2368 if (mach_result != KERN_SUCCESS) {
2369 kload_log_error("kmod destroy failed" KNL);
2370 }
2371 result = kload_error_link_load;
2372 goto finish;
2373 }
2374 }
2375
2376 if (log_level >= kload_log_level_load_basic) {
2377 kload_log_message("module # %d reference counts incremented" KNL,
2378 entry->kmod_id);
2379 }
2380
2381 finish:
2382 return result;
2383 }
2384
2385 /*******************************************************************************
2386 *
2387 *******************************************************************************/
2388 PRIV_EXT
2389 kload_error __kload_start_module(dgraph_entry_t * entry) {
2390 kload_error result = kload_error_none;
2391 int mach_result;
2392 #ifndef KERNEL
2393 void * kmod_control_args = 0;
2394 int num_args = 0;
2395 #endif /* not KERNEL */
2396
2397 if (!entry->do_load) {
2398 result = kload_error_already_loaded;
2399 goto finish;
2400 }
2401
2402 #ifndef KERNEL
2403 mach_result = kmod_control(G_kernel_priv_port,
2404 entry->kmod_id, KMOD_CNTL_START, &kmod_control_args, &num_args);
2405 #else
2406 mach_result = kmod_start_or_stop(entry->kmod_id, 1, 0, 0);
2407 #endif /* not KERNEL */
2408
2409 if (mach_result != KERN_SUCCESS) {
2410 kload_log_error(
2411 "kmod_control/start failed for %s; destroying kmod" KNL,
2412 entry->expected_kmod_name);
2413 #ifndef KERNEL
2414 mach_result = kmod_destroy(G_kernel_priv_port, entry->kmod_id);
2415 #else
2416 mach_result = kmod_destroy_internal(entry->kmod_id);
2417 #endif /* not KERNEL */
2418 if (mach_result != KERN_SUCCESS) {
2419 kload_log_error("kmod destroy failed" KNL);
2420 }
2421 result = kload_error_link_load;
2422 goto finish;
2423 }
2424
2425 if (log_level >= kload_log_level_load_basic) {
2426 kload_log_message("module # %d started" KNL,
2427 entry->kmod_id);
2428 }
2429
2430 finish:
2431 return result;
2432 }
2433
2434 /*******************************************************************************
2435 *******************************************************************************/
2436
2437 /*******************************************************************************
2438 * This function can only operate on 32 bit mach object file symbol table
2439 * graphs represented by G_current_load_entry.
2440 *******************************************************************************/
2441 static
2442 unsigned long __kload_linkedit_address(
2443 unsigned long size,
2444 unsigned long headers_size)
2445 {
2446 unsigned long round_segments_size;
2447 unsigned long round_headers_size;
2448 unsigned long round_size;
2449 int mach_result;
2450 const struct machOMapping {
2451 struct mach_header h;
2452 struct segment_command seg[1];
2453 } *machO;
2454
2455 if (!G_current_load_entry) {
2456 return 0;
2457 }
2458
2459 // the actual size allocated by kld_load_from_memory()
2460 G_current_load_entry->kernel_load_size = size;
2461
2462 round_headers_size = round_page(headers_size);
2463 round_segments_size = round_page(size - headers_size);
2464 round_size = round_headers_size + round_segments_size;
2465
2466 G_current_load_entry->kernel_alloc_size = round_size;
2467
2468 // will need to be rounded *after* load/link
2469 G_current_load_entry->kernel_hdr_size = headers_size;
2470 G_current_load_entry->kernel_hdr_pad = round_headers_size - headers_size;
2471
2472 if (G_current_load_entry->loaded_address) {
2473 G_current_load_entry->kernel_load_address =
2474 G_current_load_entry->loaded_address +
2475 G_current_load_entry->kernel_hdr_pad;
2476 if (log_level >= kload_log_level_load_basic) {
2477 kload_log_message(
2478 "using %s load address 0x%x (0x%x with header pad)" KNL,
2479 G_current_load_entry->kmod_id ? "existing" : "provided",
2480 G_current_load_entry->loaded_address,
2481 G_current_load_entry->kernel_load_address);
2482 }
2483 return G_current_load_entry->kernel_load_address;
2484 }
2485
2486 machO = (const struct machOMapping *) G_current_load_entry->object;
2487 if (machO->seg[0].vmaddr)
2488 {
2489 G_current_load_entry->loaded_address = trunc_page(machO->seg[0].vmaddr - machO->seg[0].fileoff);
2490
2491 G_current_load_entry->kernel_load_address = G_current_load_entry->loaded_address
2492 + G_current_load_entry->kernel_hdr_pad;
2493
2494 return G_current_load_entry->kernel_load_address;
2495 }
2496
2497 #ifndef KERNEL
2498 if (G_prelink) {
2499 G_current_load_entry->kernel_alloc_address = G_prelink->modules[0].address;
2500 G_prelink->modules[0].address += round_page(G_current_load_entry->kernel_alloc_size);
2501 mach_result = KERN_SUCCESS;
2502
2503 } else if (G_syms_only) {
2504 kload_log_error(
2505 "internal error; asked to allocate kernel memory" KNL);
2506 // FIXME: no provision for cleanup here
2507 return kload_error_unspecified;
2508
2509 } else
2510 #endif /* not KERNEL */
2511
2512 {
2513 #ifndef KERNEL
2514 mach_result = vm_allocate(G_kernel_port,
2515 &G_current_load_entry->kernel_alloc_address,
2516 G_current_load_entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
2517 #else
2518 mach_result = vm_allocate(kernel_map,
2519 &G_current_load_entry->kernel_alloc_address,
2520 G_current_load_entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
2521 #endif /* not KERNEL */
2522 }
2523
2524 if (mach_result != KERN_SUCCESS) {
2525 kload_log_error("can't allocate kernel memory" KNL);
2526 // FIXME: no provision for cleanup here
2527 return kload_error_kernel_error;
2528 }
2529
2530 if (log_level >= kload_log_level_load_basic) {
2531 kload_log_message("allocated %ld bytes in kernel space at 0x%x" KNL,
2532 G_current_load_entry->kernel_alloc_size,
2533 G_current_load_entry->kernel_alloc_address);
2534 }
2535
2536 G_current_load_entry->kernel_load_address =
2537 G_current_load_entry->kernel_alloc_address +
2538 G_current_load_entry->kernel_hdr_pad;
2539
2540 G_current_load_entry->loaded_address = G_current_load_entry->kernel_alloc_address;
2541
2542 if (log_level >= kload_log_level_load_basic) {
2543 kload_log_message(
2544 "using load address of 0x%x" KNL,
2545 G_current_load_entry->kernel_alloc_address);
2546 }
2547
2548 return G_current_load_entry->kernel_load_address;
2549 }
2550
2551 /*******************************************************************************
2552 *
2553 *******************************************************************************/
2554 static
2555 void __kload_clear_kld_globals(void) {
2556 G_current_load_entry = NULL;
2557 return;
2558 }
2559
2560 /*******************************************************************************
2561 *
2562 *******************************************************************************/
2563 static
2564 void __kload_clean_up_entry(dgraph_entry_t * entry) {
2565 int mach_result;
2566
2567 if (entry->need_cleanup && entry->kernel_alloc_address) {
2568 #ifndef KERNEL
2569 if (G_prelink) {
2570
2571 if ((entry->kernel_alloc_address + entry->kernel_alloc_size) == G_prelink->modules[0].address) {
2572 G_prelink->modules[0].address = entry->kernel_alloc_address;
2573 } else {
2574 kload_log_error(
2575 "bad free load address of 0x%x (last 0x%x)" KNL,
2576 entry->kernel_alloc_address, G_prelink->modules[0].address);
2577 }
2578 } else {
2579 mach_result = vm_deallocate(G_kernel_port, entry->kernel_alloc_address,
2580 entry->kernel_alloc_size);
2581 }
2582 #else
2583 mach_result = vm_deallocate(kernel_map, entry->kernel_alloc_address,
2584 entry->kernel_alloc_size);
2585 #endif /* not KERNEL */
2586 entry->kernel_alloc_address = 0;
2587 }
2588 return;
2589 }
2590
2591 #ifndef KERNEL
2592 /*******************************************************************************
2593 *
2594 *******************************************************************************/
2595 int kload_file_exists(const char * path)
2596 {
2597 int result = 0; // assume it doesn't exist
2598 struct stat stat_buf;
2599
2600 if (stat(path, &stat_buf) == 0) {
2601 result = 1; // the file does exist; we don't care beyond that
2602 goto finish;
2603 }
2604
2605 switch (errno) {
2606 case ENOENT:
2607 result = 0; // the file doesn't exist
2608 goto finish;
2609 break;
2610 default:
2611 result = -1; // unknown error
2612 goto finish;
2613 break;
2614 }
2615
2616 finish:
2617 return result;
2618 }
2619 #endif /* not KERNEL */
2620
2621 /*******************************************************************************
2622 *
2623 *******************************************************************************/
2624 PRIV_EXT
2625 void kload_set_log_level(kload_log_level level)
2626 {
2627 log_level = level;
2628 return;
2629 }
2630
2631 #ifndef KERNEL
2632 /*******************************************************************************
2633 *
2634 *******************************************************************************/
2635 void kload_set_log_function(
2636 void (*func)(const char * format, ...))
2637 {
2638 if (!func) {
2639 __kload_log_func = &__kload_null_log;
2640 } else {
2641 __kload_log_func = func;
2642 }
2643 return;
2644 }
2645
2646 /*******************************************************************************
2647 *
2648 *******************************************************************************/
2649 void kload_set_error_log_function(
2650 void (*func)(const char * format, ...))
2651 {
2652 if (!func) {
2653 __kload_err_log_func = &__kload_null_err_log;
2654 } else {
2655 __kload_err_log_func = func;
2656 }
2657 return;
2658 }
2659
2660 /*******************************************************************************
2661 *
2662 *******************************************************************************/
2663 void kload_set_user_approve_function(
2664 int (*func)(int default_answer, const char * format, ...))
2665 {
2666 if (!func) {
2667 __kload_approve_func = &__kload_null_approve;
2668 } else {
2669 __kload_approve_func = func;
2670 }
2671 return;
2672 }
2673
2674 /*******************************************************************************
2675 *
2676 *******************************************************************************/
2677 void kload_set_user_veto_function(
2678 int (*func)(int default_answer, const char * format, ...))
2679 {
2680 if (!func) {
2681 __kload_veto_func = &__kload_null_veto;
2682 } else {
2683 __kload_veto_func = func;
2684 }
2685 return;
2686 }
2687
2688 /*******************************************************************************
2689 *
2690 *******************************************************************************/
2691 void kload_set_user_input_function(
2692 const char * (*func)(const char * format, ...))
2693 {
2694 if (!func) {
2695 __kload_input_func = &__kload_null_input;
2696 } else {
2697 __kload_input_func = func;
2698 }
2699 return;
2700 }
2701
2702 /*******************************************************************************
2703 *
2704 *******************************************************************************/
2705 PRIV_EXT
2706 void kload_log_message(const char * format, ...)
2707 {
2708 va_list ap;
2709 char fake_buffer[2];
2710 int output_length;
2711 char * output_string;
2712
2713 if (log_level <= kload_log_level_silent) {
2714 return;
2715 }
2716
2717 va_start(ap, format);
2718 output_length = vsnprintf(fake_buffer, 1, format, ap);
2719 va_end(ap);
2720
2721 output_string = (char *)malloc(output_length + 1);
2722 if (!output_string) {
2723 return;
2724 }
2725
2726 va_start(ap, format);
2727 vsprintf(output_string, format, ap);
2728 va_end(ap);
2729
2730 __kload_log_func(output_string);
2731 free(output_string);
2732
2733 return;
2734 }
2735
2736 /*******************************************************************************
2737 *
2738 *******************************************************************************/
2739 PRIV_EXT
2740 void kload_log_error(const char * format, ...)
2741 {
2742 va_list ap;
2743 char fake_buffer[2];
2744 int output_length;
2745 char * output_string;
2746
2747 if (log_level <= kload_log_level_silent) {
2748 return;
2749 }
2750
2751 va_start(ap, format);
2752 output_length = vsnprintf(fake_buffer, 1, format, ap);
2753 va_end(ap);
2754
2755 output_string = (char *)malloc(output_length + 1);
2756 if (!output_string) {
2757 return;
2758 }
2759
2760 va_start(ap, format);
2761 vsprintf(output_string, format, ap);
2762 va_end(ap);
2763
2764 __kload_err_log_func(output_string);
2765 free(output_string);
2766
2767 return;
2768 }
2769 /*******************************************************************************
2770 *
2771 *******************************************************************************/
2772 void __kload_null_log(const char * format, ...)
2773 {
2774 return;
2775 }
2776
2777 /*******************************************************************************
2778 *
2779 *******************************************************************************/
2780 void __kload_null_err_log(const char * format, ...)
2781 {
2782 return;
2783 }
2784
2785 /*******************************************************************************
2786 *
2787 *******************************************************************************/
2788 int __kload_null_approve(int default_answer, const char * format, ...)
2789 {
2790 return 0;
2791 }
2792
2793 /*******************************************************************************
2794 *
2795 *******************************************************************************/
2796 int __kload_null_veto(int default_answer, const char * format, ...)
2797 {
2798 return 1;
2799 }
2800
2801 /*******************************************************************************
2802 *
2803 *******************************************************************************/
2804 const char * __kload_null_input(const char * format, ...)
2805 {
2806 return NULL;
2807 }
2808
2809 /*******************************************************************************
2810 * The kld_patch.c module uses this function, if defined, to print errors. In
2811 * the kernel this function is defined in libsa/misc.c.
2812 *******************************************************************************/
2813 void kld_error_vprintf(const char * format, va_list ap) {
2814 if (log_level <= kload_log_level_silent) return;
2815 vfprintf(stderr, format, ap);
2816 return;
2817 }
2818
2819 #endif /* not KERNEL */