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