]> git.saurik.com Git - apple/xnu.git/blame - libsa/load.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / libsa / load.c
CommitLineData
91447636
A
1/*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
91447636 5 *
8f6c56a5
A
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
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
91447636
A
27 */
28
55e303ae
A
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
91447636 49#include <mach/mach_types.h>
55e303ae
A
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>
91447636
A
60#include <kern/kern_types.h>
61#include <kern/kalloc.h>
55e303ae
A
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
108extern kern_return_t
109kmod_create_internal(
110 kmod_info_t *info,
111 kmod_t *id);
112
113extern kern_return_t
114kmod_destroy_internal(kmod_t id);
115
116extern kern_return_t
117kmod_start_or_stop(
118 kmod_t id,
119 int start,
120 kmod_args_t *data,
121 mach_msg_type_number_t *dataCount);
122
123extern kern_return_t kmod_retain(kmod_t id);
124extern kern_return_t kmod_release(kmod_t id);
125
91447636 126extern struct mach_header _mh_execute_header;
55e303ae
A
127#endif /* KERNEL */
128
129
130// Used to pass info between kld library and callbacks
131static dgraph_entry_t * G_current_load_entry = NULL;
132
133#ifndef KERNEL
134static mach_port_t G_kernel_port = PORT_NULL;
135static mach_port_t G_kernel_priv_port = PORT_NULL;
136static int G_syms_only;
137
138static kload_error
139register_prelink(dgraph_entry_t * entry,
140 kmod_info_t * local_kmod_info, vm_offset_t kernel_kmod_info);
141
142struct PrelinkState
143{
144 kmod_info_t modules[1];
145};
146struct PrelinkState * G_prelink;
147CFMutableDataRef G_prelink_data;
148CFMutableDataRef G_prelink_dependencies;
149
150#endif /* not KERNEL */
151
152// used by dgraph.c so can't be static
153kload_log_level log_level = 0;
154
155#ifndef KERNEL
156static void __kload_null_log(const char * format, ...);
157static void __kload_null_err_log(const char * format, ...);
158static int __kload_null_approve(int default_answer, const char * format, ...);
159static int __kload_null_veto(int default_answer, const char * format, ...);
160static const char * __kload_null_input(const char * format, ...);
161
162void (*__kload_log_func)(const char * format, ...) =
163 &__kload_null_log;
164void (*__kload_err_log_func)(const char * format, ...) = &__kload_null_err_log;
165int (*__kload_approve_func)(int default_answer,
166 const char * format, ...) = &__kload_null_approve;
167int (*__kload_veto_func)(int default_answer,
168 const char * format, ...) = &__kload_null_veto;
169const char * (*__kload_input_func)(const char * format, ...) =
170 &__kload_null_input;
171#endif /* not KERNEL */
172
173static unsigned long __kload_linkedit_address(
174 unsigned long size,
175 unsigned long headers_size);
176static void __kload_clean_up_entry(dgraph_entry_t * entry);
177static void __kload_clear_kld_globals(void);
178static kload_error __kload_patch_dgraph(dgraph_t * dgraph
179#ifndef KERNEL
180 ,
181 const char * kernel_file
182#endif /* not KERNEL */
183 );
184static 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
196static 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
204static 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 );
217static kload_error __kload_set_module_dependencies(dgraph_entry_t * entry);
218static kload_error __kload_start_module(dgraph_entry_t * entry);
219
220#ifndef KERNEL
221static 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
228Boolean _IOReadBytesFromFile(CFAllocatorRef alloc, const char *path, void **bytes,
229 CFIndex *length, CFIndex maxLength);
230Boolean _IOWriteBytesToFile(const char *path, const void *bytes, CFIndex length);
231
232#endif /* not KERNEL */
233
234/*******************************************************************************
235*
236*******************************************************************************/
237PRIV_EXT
238kload_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
426finish:
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*******************************************************************************/
478kload_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
514finish:
515 return result;
516}
517#endif /* not KERNEL */
518/*******************************************************************************
91447636
A
519* This function can only operate on 32 bit mach object file symbol table
520* entries.
55e303ae
A
521*******************************************************************************/
522static
523kload_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
533 if (entry->symbols)
534 return kload_error_none;
535
536 hdr = entry->linked_image;
537 ncmds = hdr->ncmds;
538 seg = (struct segment_command *)(hdr + 1);
539 for (idx = 0;
540 idx < ncmds;
541 idx++, seg = (struct segment_command *)(((vm_offset_t)seg) + seg->cmdsize))
542 {
543 if (LC_SYMTAB == seg->cmd)
544 break;
545 }
546 if (idx >= ncmds)
547 {
548 kload_log_error("no LC_SYMTAB" KNL);
549 return kload_error_unspecified;
550 }
551
552 symcmd = (struct symtab_command *) seg;
553
554 struct load_cmds {
555 struct mach_header hdr;
556 struct segment_command seg;
557 struct symtab_command symcmd;
558 };
559 struct load_cmds * cmd;
560 unsigned int symtabsize;
561
562 symtabsize = symcmd->stroff + symcmd->strsize - symcmd->symoff;
563
564 size = sizeof(struct load_cmds) + symtabsize;
565
566 mem = (vm_offset_t) malloc(size);
567
568 cmd = (struct load_cmds *) mem;
569 sym = (struct nlist *) (cmd + 1);
570
571 cmd->hdr = *hdr;
572 cmd->symcmd = *symcmd;
573 bcopy((const void *) (((vm_offset_t) hdr) + symcmd->symoff),
574 sym,
575 symtabsize);
576
577 hdr = (struct mach_header *) mem;
578 cmd->hdr.ncmds = 2;
91447636 579 cmd->hdr.sizeofcmds = sizeof(struct load_cmds) - sizeof(struct mach_header);
55e303ae
A
580 cmd->hdr.flags &= ~MH_INCRLINK;
581
582 cmd->symcmd.stroff -= (symcmd->symoff - sizeof(struct load_cmds));
583 cmd->symcmd.symoff = sizeof(struct load_cmds);
584
585 cmd->seg.cmd = LC_SEGMENT;
586 cmd->seg.cmdsize = sizeof(struct segment_command);
587 strcpy(cmd->seg.segname, SEG_LINKEDIT);
588 cmd->seg.vmaddr = 0;
589 cmd->seg.vmsize = 0;
590 cmd->seg.fileoff = cmd->symcmd.symoff;
591 cmd->seg.filesize = symtabsize;
592 cmd->seg.maxprot = 7;
593 cmd->seg.initprot = 1;
594 cmd->seg.nsects = 0;
595 cmd->seg.flags = 0;
596
597 sym = (struct nlist *) (cmd + 1);
598 for (idx = 0; idx < symcmd->nsyms; idx++, sym++)
599 {
91447636
A
600 if ( (sym->n_type & N_STAB) != 0)
601 {
602 sym->n_type = N_ABS;
603 sym->n_desc = 0;
604 sym->n_value = sym->n_un.n_strx;
605 sym->n_un.n_strx = 0;
606 sym->n_sect = NO_SECT;
607 }
608 else if ( (sym->n_type & N_TYPE) == N_SECT)
609 {
55e303ae
A
610 sym->n_sect = NO_SECT;
611 sym->n_type = (sym->n_type & ~N_TYPE) | N_ABS;
612 }
613 }
614 if (log_level >= kload_log_level_load_details)
615 {
616 kload_log_message("__kload_keep_symbols %s, nsyms %ld, 0x%x bytes" KNL,
617 entry->name, symcmd->nsyms, size);
618 }
619
620 entry->symbols = mem;
621 entry->symbols_malloc = mem;
622 entry->symbols_length = size;
623
624 return kload_error_none;
625}
626
627
91447636
A
628/*******************************************************************************
629* This function can only operate on 32 bit mach object files
630*******************************************************************************/
55e303ae
A
631static
632kload_error __kload_make_opaque_basefile(dgraph_t * dgraph, struct mach_header * hdr)
633{
634 struct segment_command * seg;
635 struct segment_command * data_seg;
636 struct segment_command * text_seg;
637 struct section * sec;
91447636 638 unsigned int j;
55e303ae
A
639 vm_offset_t offset;
640 unsigned long idx, ncmds;
641 vm_size_t size;
642 vm_address_t mem, out;
643 static vm_address_t keep_base_image;
644 static vm_size_t keep_base_size;
645
646 if (dgraph->opaque_base_image)
647 return kload_error_none;
648
649 if (keep_base_image)
650 {
651 dgraph->opaque_base_image = keep_base_image;
652 dgraph->opaque_base_length = keep_base_size;
653 return kload_error_none;
654 }
655
656 data_seg = text_seg = NULL;
657 ncmds = hdr->ncmds;
658 seg = (struct segment_command *)(hdr + 1);
659 for (idx = 0;
660 idx < ncmds;
661 idx++, seg = (struct segment_command *)(((vm_offset_t)seg) + seg->cmdsize))
662 {
663 if (LC_SEGMENT != seg->cmd)
664 continue;
665 if (!strcmp(SEG_TEXT, seg->segname))
666 text_seg = seg;
667 else if (!strcmp(SEG_DATA, seg->segname))
668 data_seg = seg;
669 }
670 if (!text_seg || !data_seg)
671 {
672 kload_log_error("no SEG_TEXT or SEG_DATA" KNL);
673 return kload_error_unspecified;
674 }
675
676 size = sizeof(struct mach_header) + text_seg->cmdsize + data_seg->cmdsize;
677 mem = (vm_offset_t) malloc(size);
678
679 out = mem;
680 bcopy(hdr, (void *) out, sizeof(struct mach_header));
681 hdr = (struct mach_header *) out;
682 out += sizeof(struct mach_header);
683
684 bcopy(text_seg, (void *) out, text_seg->cmdsize);
685 text_seg = (struct segment_command *) out;
686 out += text_seg->cmdsize;
687
688 bcopy(data_seg, (void *) out, data_seg->cmdsize);
689 data_seg = (struct segment_command *) out;
690 out += data_seg->cmdsize;
691
692 hdr->ncmds = 2;
693 hdr->sizeofcmds = text_seg->cmdsize + data_seg->cmdsize;
694
695 offset = hdr->sizeofcmds;
696
697 text_seg->fileoff = offset;
698 text_seg->filesize = 0;
699
700 sec = (struct section *)(text_seg + 1);
701 for (j = 0; j < text_seg->nsects; j++, sec++)
702 {
703// sec->addr = (unsigned long) addr;
704 sec->size = 0;
705 sec->offset = offset;
706 sec->nreloc = 0;
707 }
708
709 data_seg->fileoff = offset;
710 data_seg->filesize = 0;
711
712 sec = (struct section *)(data_seg + 1);
713 for (j = 0; j < data_seg->nsects; j++, sec++)
714 {
715// sec->addr = (unsigned long) addr;
716 sec->size = 0;
717 sec->offset = offset;
718 sec->nreloc = 0;
719 }
720
721 dgraph->opaque_base_image = mem;
722 dgraph->opaque_base_length = size;
723 keep_base_image = mem;
724 keep_base_size = size;
725
726 return kload_error_none;
727}
728
729/*******************************************************************************
730*
731*******************************************************************************/
732static
733kload_error __kload_load_modules(dgraph_t * dgraph
734#ifndef KERNEL
735 ,
736 const char * kernel_file,
737 const char * patch_file,
738 const char * patch_dir,
739 const char * symbol_file,
740 const char * symbol_dir,
741 int do_load,
742 int do_start_kmod,
743 int do_prelink,
744 int interactive_level,
745 int ask_overwrite_symbols,
746 int overwrite_symbols
747#endif /* not KERNEL */
748 )
749{
750 kload_error result = kload_error_none;
751#ifndef KERNEL
752 long int kernel_size = 0;
753 kern_return_t mach_result = KERN_SUCCESS;
754#endif /* not KERNEL */
755 char * kernel_base_addr = 0;
756 int kld_result;
757 Boolean cleanup_kld_loader = false;
758 unsigned int i;
759
760 /* We have to map all object files to get their CFBundleIdentifier
761 * names.
762 */
763#ifndef KERNEL
764 result = kload_map_dgraph(dgraph, kernel_file);
765#else
766 result = kload_map_dgraph(dgraph);
767#endif /* not KERNEL */
768 if (result != kload_error_none) {
769 kload_log_error("error mapping object files" KNL);
770 goto finish;
771 }
772
773#ifndef KERNEL
774 result = __kload_patch_dgraph(dgraph, kernel_file);
775#else
776 result = __kload_patch_dgraph(dgraph);
777#endif /* not KERNEL */
778 if (result != kload_error_none) {
779 // FIXME: print an error message here?
780 goto finish;
781 }
782
783#ifndef KERNEL
784 // FIXME: check error return
785 __kload_output_patches(dgraph, patch_file, patch_dir,
786 ask_overwrite_symbols, overwrite_symbols);
787
788 /*****
789 * If we're not loading or writing symbols, we're done.
790 */
791 if (!do_load && !do_prelink && !symbol_file && !symbol_dir) {
792 goto finish;
793 }
794
795 if (do_load && PORT_NULL == G_kernel_port) {
796 mach_result = task_for_pid(mach_task_self(), 0, &G_kernel_port);
797 if (mach_result != KERN_SUCCESS) {
798 kload_log_error("unable to get kernel task port: %s" KNL,
799 mach_error_string(mach_result));
800 kload_log_error("you must be running as root to load "
801 "modules into the kernel" KNL);
802 result = kload_error_kernel_permission;
803 goto finish;
804 }
805 }
806#endif /* not KERNEL */
807
808 kld_address_func(&__kload_linkedit_address);
809
810#ifndef KERNEL
811 G_syms_only = (!do_load) && (symbol_file || symbol_dir || patch_dir);
812
813 kernel_base_addr = kld_file_getaddr(kernel_file, &kernel_size);
814 if (!kernel_base_addr) {
815 kload_log_error(
816 "can't get load address for kernel %s" KNL, kernel_file);
817 result = kload_error_link_load;
818 goto finish;
819 }
820#else /* KERNEL */
821
822 const char * kernel_file = "(kernel)";
55e303ae
A
823 kernel_base_addr = (char *) &_mh_execute_header;
824
825#endif /* not KERNEL */
826
827 kld_result = true;
828 if (dgraph->has_symbol_sets)
829 {
830 result = __kload_make_opaque_basefile(dgraph, (struct mach_header *) kernel_base_addr);
831 if (result != kload_error_none) {
832 kload_log_error("can't construct opaque base image from %s" KNL, kernel_file);
833 goto finish;
834 }
835
836 kld_result = kld_load_basefile_from_memory(kernel_file,
837 (char *) dgraph->opaque_base_image,
838 dgraph->opaque_base_length);
839 }
840#ifndef KERNEL
841 else
842 kld_result = kld_load_basefile_from_memory(kernel_file,
843 (char *) kernel_base_addr, kernel_size);
844#endif /* not KERNEL */
845
846 if (!kld_result) {
847 kload_log_error("can't link base image %s" KNL, kernel_file);
848 result = kload_error_link_load;
849 goto finish;
850 }
851
852 cleanup_kld_loader = true;
91447636 853 char opaque_now = false;
55e303ae
A
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
91447636 860 if (kOpaqueLink & opaque_now)
55e303ae
A
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);
91447636
A
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 }
55e303ae
A
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
91447636 892 for (j = 0; j < i; j++)
55e303ae 893 {
55e303ae 894
91447636
A
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 }
55e303ae 918
55e303ae
A
919 if (!image_dep->symbols)
920 {
921 kload_log_error("internal error; no dependent symbols" KNL);
91447636 922 result = kload_error_link_load;
55e303ae
A
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 {
91447636
A
971 if (!(kRawKernelLink & current_entry->opaques)) {
972 result = __kload_keep_symbols(current_entry);
973 }
55e303ae
A
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 (ansering 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
1057finish:
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
1086static
1087kload_error __kload_load_module(dgraph_t * dgraph,
1088 dgraph_entry_t * entry,
91447636
A
1089#ifdef KERNEL
1090 __unused int is_root
1091#else /* not KERNEL */
1092 int is_root,
55e303ae
A
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 strcpy(local_kmod_info->name, entry->expected_kmod_name);
1329
1330 bzero(local_kmod_info->version, sizeof(local_kmod_info->version));
1331 strcpy(local_kmod_info->version, entry->expected_kmod_vers);
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,
91447636 1373 entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
55e303ae
A
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
1457finish:
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
1476static kload_error
1477register_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*******************************************************************************/
1552PRIV_EXT
1553#ifndef KERNEL
1554kload_error kload_map_dgraph(
1555 dgraph_t * dgraph,
1556 const char * kernel_file)
1557#else
1558kload_error kload_map_dgraph(
1559 dgraph_t * dgraph)
1560#endif /* not KERNEL */
1561{
1562 kload_error result = kload_error_none;
91447636 1563 unsigned int i;
55e303ae
A
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
1593finish:
1594 return result;
1595
1596}
1597
1598/*******************************************************************************
1599*
1600*******************************************************************************/
1601PRIV_EXT
1602kload_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
1663finish:
1664 return result;
1665}
1666
1667#ifndef KERNEL
1668/*******************************************************************************
1669*
1670*******************************************************************************/
1671kload_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
1724finish:
1725 return result;
1726
1727}
1728
1729/*******************************************************************************
1730* addresses is a NULL-terminated list of string of the form "module_id@address"
1731*******************************************************************************/
1732kload_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
1818finish:
1819 return result;
1820
1821}
1822
1823/*******************************************************************************
1824* This function requires G_kernel_priv_port to be set before it will work.
1825*******************************************************************************/
1826kload_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
1888finish:
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*******************************************************************************/
1903PRIV_EXT
1904kload_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
1957finish:
1958
1959 return result;
1960}
1961#endif /* not KERNEL */
1962
1963/*******************************************************************************
1964*
1965*******************************************************************************/
1966#ifdef KERNEL
1967extern kern_return_t kmod_load_from_cache(const char * kmod_name);
1968#endif /* KERNEL */
1969
1970static 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*******************************************************************************/
2003static
2004kload_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
2100finish:
2101#ifdef KERNEL
2102 // Do this ONLY if in the kernel!
2103 if (current_kmod) {
91447636 2104 kfree(current_kmod, sizeof(kmod_info_t));
55e303ae
A
2105 }
2106#endif /* KERNEL */
2107 return result;
2108}
2109
2110/*******************************************************************************
2111*
2112*******************************************************************************/
2113PRIV_EXT
2114kload_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
2184finish:
2185 return result;
2186}
2187
2188#ifndef KERNEL
2189/*******************************************************************************
2190*
2191*******************************************************************************/
2192#define __KLOAD_PATCH_EXTENSION ".patch"
2193
2194kload_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 strcpy(patch_filename, patch_dir);
2241 strcat(patch_filename, "/");
2242 strcat(patch_filename, entry->expected_kmod_name);
2243 strcat(patch_filename, __KLOAD_PATCH_EXTENSION);
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
2314finish:
2315 if (allocated_filename) free(allocated_filename);
2316
2317 return result;
2318}
2319#endif /* not KERNEL */
2320
2321/*******************************************************************************
2322*
2323*******************************************************************************/
2324PRIV_EXT
2325kload_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
2379finish:
2380 return result;
2381}
2382
2383/*******************************************************************************
2384*
2385*******************************************************************************/
2386PRIV_EXT
2387kload_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#endif /* not KERNEL */
2394
2395 if (!entry->do_load) {
2396 result = kload_error_already_loaded;
2397 goto finish;
2398 }
2399
2400#ifndef KERNEL
2401 mach_result = kmod_control(G_kernel_priv_port,
2402 entry->kmod_id, KMOD_CNTL_START, &kmod_control_args, &num_args);
2403#else
2404 mach_result = kmod_start_or_stop(entry->kmod_id, 1, 0, 0);
2405#endif /* not KERNEL */
2406
2407 if (mach_result != KERN_SUCCESS) {
2408 kload_log_error(
2409 "kmod_control/start failed for %s; destroying kmod" KNL,
2410 entry->expected_kmod_name);
2411#ifndef KERNEL
2412 mach_result = kmod_destroy(G_kernel_priv_port, entry->kmod_id);
2413#else
2414 mach_result = kmod_destroy_internal(entry->kmod_id);
2415#endif /* not KERNEL */
2416 if (mach_result != KERN_SUCCESS) {
2417 kload_log_error("kmod destroy failed" KNL);
2418 }
2419 result = kload_error_link_load;
2420 goto finish;
2421 }
2422
2423 if (log_level >= kload_log_level_load_basic) {
2424 kload_log_message("module # %d started" KNL,
2425 entry->kmod_id);
2426 }
2427
2428finish:
2429 return result;
2430}
2431
2432/*******************************************************************************
2433*******************************************************************************/
2434
2435/*******************************************************************************
91447636
A
2436* This function can only operate on 32 bit mach object file symbol table
2437* graphs represented by G_current_load_entry.
55e303ae
A
2438*******************************************************************************/
2439static
2440unsigned long __kload_linkedit_address(
2441 unsigned long size,
2442 unsigned long headers_size)
2443{
2444 unsigned long round_segments_size;
2445 unsigned long round_headers_size;
2446 unsigned long round_size;
2447 int mach_result;
2448 const struct machOMapping {
2449 struct mach_header h;
2450 struct segment_command seg[1];
2451 } *machO;
2452
2453 if (!G_current_load_entry) {
2454 return 0;
2455 }
2456
2457 // the actual size allocated by kld_load_from_memory()
2458 G_current_load_entry->kernel_load_size = size;
2459
2460 round_headers_size = round_page(headers_size);
2461 round_segments_size = round_page(size - headers_size);
2462 round_size = round_headers_size + round_segments_size;
2463
2464 G_current_load_entry->kernel_alloc_size = round_size;
2465
2466 // will need to be rounded *after* load/link
2467 G_current_load_entry->kernel_hdr_size = headers_size;
2468 G_current_load_entry->kernel_hdr_pad = round_headers_size - headers_size;
2469
2470 if (G_current_load_entry->loaded_address) {
2471 G_current_load_entry->kernel_load_address =
2472 G_current_load_entry->loaded_address +
2473 G_current_load_entry->kernel_hdr_pad;
2474 if (log_level >= kload_log_level_load_basic) {
2475 kload_log_message(
2476 "using %s load address 0x%x (0x%x with header pad)" KNL,
2477 G_current_load_entry->kmod_id ? "existing" : "provided",
2478 G_current_load_entry->loaded_address,
2479 G_current_load_entry->kernel_load_address);
2480 }
2481 return G_current_load_entry->kernel_load_address;
2482 }
2483
2484 machO = (const struct machOMapping *) G_current_load_entry->object;
2485 if (machO->seg[0].vmaddr)
2486 {
2487 G_current_load_entry->loaded_address = trunc_page(machO->seg[0].vmaddr - machO->seg[0].fileoff);
2488
2489 G_current_load_entry->kernel_load_address = G_current_load_entry->loaded_address
2490 + G_current_load_entry->kernel_hdr_pad;
2491
2492 return G_current_load_entry->kernel_load_address;
2493 }
2494
2495#ifndef KERNEL
2496 if (G_prelink) {
2497 G_current_load_entry->kernel_alloc_address = G_prelink->modules[0].address;
2498 G_prelink->modules[0].address += round_page(G_current_load_entry->kernel_alloc_size);
2499 mach_result = KERN_SUCCESS;
2500
2501 } else if (G_syms_only) {
2502 kload_log_error(
2503 "internal error; asked to allocate kernel memory" KNL);
2504 // FIXME: no provision for cleanup here
2505 return kload_error_unspecified;
2506
2507 } else
2508#endif /* not KERNEL */
2509
2510 {
2511#ifndef KERNEL
2512 mach_result = vm_allocate(G_kernel_port,
2513 &G_current_load_entry->kernel_alloc_address,
91447636 2514 G_current_load_entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
55e303ae
A
2515#else
2516 mach_result = vm_allocate(kernel_map,
2517 &G_current_load_entry->kernel_alloc_address,
91447636 2518 G_current_load_entry->kernel_alloc_size, VM_FLAGS_ANYWHERE);
55e303ae
A
2519#endif /* not KERNEL */
2520 }
2521
2522 if (mach_result != KERN_SUCCESS) {
2523 kload_log_error("can't allocate kernel memory" KNL);
2524 // FIXME: no provision for cleanup here
2525 return kload_error_kernel_error;
2526 }
2527
2528 if (log_level >= kload_log_level_load_basic) {
2529 kload_log_message("allocated %ld bytes in kernel space at 0x%x" KNL,
2530 G_current_load_entry->kernel_alloc_size,
2531 G_current_load_entry->kernel_alloc_address);
2532 }
2533
2534 G_current_load_entry->kernel_load_address =
2535 G_current_load_entry->kernel_alloc_address +
2536 G_current_load_entry->kernel_hdr_pad;
2537
2538 G_current_load_entry->loaded_address = G_current_load_entry->kernel_alloc_address;
2539
2540 if (log_level >= kload_log_level_load_basic) {
2541 kload_log_message(
2542 "using load address of 0x%x" KNL,
2543 G_current_load_entry->kernel_alloc_address);
2544 }
2545
2546 return G_current_load_entry->kernel_load_address;
2547}
2548
2549/*******************************************************************************
2550*
2551*******************************************************************************/
2552static
2553void __kload_clear_kld_globals(void) {
2554 G_current_load_entry = NULL;
2555 return;
2556}
2557
2558/*******************************************************************************
2559*
2560*******************************************************************************/
2561static
2562void __kload_clean_up_entry(dgraph_entry_t * entry) {
2563 int mach_result;
2564
2565 if (entry->need_cleanup && entry->kernel_alloc_address) {
2566#ifndef KERNEL
2567 if (G_prelink) {
2568
2569 if ((entry->kernel_alloc_address + entry->kernel_alloc_size) == G_prelink->modules[0].address) {
2570 G_prelink->modules[0].address = entry->kernel_alloc_address;
2571 } else {
2572 kload_log_error(
2573 "bad free load address of 0x%x (last 0x%x)" KNL,
2574 entry->kernel_alloc_address, G_prelink->modules[0].address);
2575 }
2576 } else {
2577 mach_result = vm_deallocate(G_kernel_port, entry->kernel_alloc_address,
2578 entry->kernel_alloc_size);
2579 }
2580#else
2581 mach_result = vm_deallocate(kernel_map, entry->kernel_alloc_address,
2582 entry->kernel_alloc_size);
2583#endif /* not KERNEL */
2584 entry->kernel_alloc_address = 0;
2585 }
2586 return;
2587}
2588
2589#ifndef KERNEL
2590/*******************************************************************************
2591*
2592*******************************************************************************/
2593int kload_file_exists(const char * path)
2594{
2595 int result = 0; // assume it doesn't exist
2596 struct stat stat_buf;
2597
2598 if (stat(path, &stat_buf) == 0) {
2599 result = 1; // the file does exist; we don't care beyond that
2600 goto finish;
2601 }
2602
2603 switch (errno) {
2604 case ENOENT:
2605 result = 0; // the file doesn't exist
2606 goto finish;
2607 break;
2608 default:
2609 result = -1; // unknown error
2610 goto finish;
2611 break;
2612 }
2613
2614finish:
2615 return result;
2616}
2617#endif /* not KERNEL */
2618
2619/*******************************************************************************
2620*
2621*******************************************************************************/
2622PRIV_EXT
2623void kload_set_log_level(kload_log_level level)
2624{
2625 log_level = level;
2626 return;
2627}
2628
2629#ifndef KERNEL
2630/*******************************************************************************
2631*
2632*******************************************************************************/
2633void kload_set_log_function(
2634 void (*func)(const char * format, ...))
2635{
2636 if (!func) {
2637 __kload_log_func = &__kload_null_log;
2638 } else {
2639 __kload_log_func = func;
2640 }
2641 return;
2642}
2643
2644/*******************************************************************************
2645*
2646*******************************************************************************/
2647void kload_set_error_log_function(
2648 void (*func)(const char * format, ...))
2649{
2650 if (!func) {
2651 __kload_err_log_func = &__kload_null_err_log;
2652 } else {
2653 __kload_err_log_func = func;
2654 }
2655 return;
2656}
2657
2658/*******************************************************************************
2659*
2660*******************************************************************************/
2661void kload_set_user_approve_function(
2662 int (*func)(int default_answer, const char * format, ...))
2663{
2664 if (!func) {
2665 __kload_approve_func = &__kload_null_approve;
2666 } else {
2667 __kload_approve_func = func;
2668 }
2669 return;
2670}
2671
2672/*******************************************************************************
2673*
2674*******************************************************************************/
2675void kload_set_user_veto_function(
2676 int (*func)(int default_answer, const char * format, ...))
2677{
2678 if (!func) {
2679 __kload_veto_func = &__kload_null_veto;
2680 } else {
2681 __kload_veto_func = func;
2682 }
2683 return;
2684}
2685
2686/*******************************************************************************
2687*
2688*******************************************************************************/
2689void kload_set_user_input_function(
2690 const char * (*func)(const char * format, ...))
2691{
2692 if (!func) {
2693 __kload_input_func = &__kload_null_input;
2694 } else {
2695 __kload_input_func = func;
2696 }
2697 return;
2698}
2699
2700/*******************************************************************************
2701*
2702*******************************************************************************/
2703PRIV_EXT
2704void kload_log_message(const char * format, ...)
2705{
2706 va_list ap;
2707 char fake_buffer[2];
2708 int output_length;
2709 char * output_string;
2710
2711 if (log_level <= kload_log_level_silent) {
2712 return;
2713 }
2714
2715 va_start(ap, format);
2716 output_length = vsnprintf(fake_buffer, 1, format, ap);
2717 va_end(ap);
2718
2719 output_string = (char *)malloc(output_length + 1);
2720 if (!output_string) {
2721 return;
2722 }
2723
2724 va_start(ap, format);
2725 vsprintf(output_string, format, ap);
2726 va_end(ap);
2727
2728 __kload_log_func(output_string);
2729 free(output_string);
2730
2731 return;
2732}
2733
2734/*******************************************************************************
2735*
2736*******************************************************************************/
2737PRIV_EXT
2738void kload_log_error(const char * format, ...)
2739{
2740 va_list ap;
2741 char fake_buffer[2];
2742 int output_length;
2743 char * output_string;
2744
2745 if (log_level <= kload_log_level_silent) {
2746 return;
2747 }
2748
2749 va_start(ap, format);
2750 output_length = vsnprintf(fake_buffer, 1, format, ap);
2751 va_end(ap);
2752
2753 output_string = (char *)malloc(output_length + 1);
2754 if (!output_string) {
2755 return;
2756 }
2757
2758 va_start(ap, format);
2759 vsprintf(output_string, format, ap);
2760 va_end(ap);
2761
2762 __kload_err_log_func(output_string);
2763 free(output_string);
2764
2765 return;
2766}
2767/*******************************************************************************
2768*
2769*******************************************************************************/
2770void __kload_null_log(const char * format, ...)
2771{
2772 return;
2773}
2774
2775/*******************************************************************************
2776*
2777*******************************************************************************/
2778void __kload_null_err_log(const char * format, ...)
2779{
2780 return;
2781}
2782
2783/*******************************************************************************
2784*
2785*******************************************************************************/
2786int __kload_null_approve(int default_answer, const char * format, ...)
2787{
2788 return 0;
2789}
2790
2791/*******************************************************************************
2792*
2793*******************************************************************************/
2794int __kload_null_veto(int default_answer, const char * format, ...)
2795{
2796 return 1;
2797}
2798
2799/*******************************************************************************
2800*
2801*******************************************************************************/
2802const char * __kload_null_input(const char * format, ...)
2803{
2804 return NULL;
2805}
2806
2807/*******************************************************************************
2808* The kld_patch.c module uses this function, if defined, to print errors. In
2809* the kernel this function is defined in libsa/misc.c.
2810*******************************************************************************/
2811void kld_error_vprintf(const char * format, va_list ap) {
2812 if (log_level <= kload_log_level_silent) return;
2813 vfprintf(stderr, format, ap);
2814 return;
2815}
2816
2817#endif /* not KERNEL */