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