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