]> git.saurik.com Git - apple/xnu.git/blob - libsa/kmod.cpp
301fa5db2c524f3d8668253665928aee027f5727
[apple/xnu.git] / libsa / kmod.cpp
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 #include <libsa/kmod.h>
26 #include <libkern/c++/OSContainers.h>
27 #include <IOKit/IOCatalogue.h>
28 #include <IOKit/IOLib.h>
29 #include <libsa/kmod.h>
30 #include <libsa/catalogue.h>
31
32 extern "C" {
33 #include <mach-o/kld.h>
34 #include <libsa/vers_rsrc.h>
35 #include <libsa/stdlib.h>
36 #include <mach/kmod.h>
37 #include <vm/vm_kern.h>
38 #include <mach/kern_return.h>
39 #include <mach-o/fat.h>
40 #include <mach_loader.h>
41 };
42
43 #include "kld_patch.h"
44
45
46 extern "C" {
47 extern kern_return_t
48 kmod_create_internal(
49 kmod_info_t *info,
50 kmod_t *id);
51
52 extern kern_return_t
53 kmod_destroy_internal(kmod_t id);
54
55 extern kern_return_t
56 kmod_start_or_stop(
57 kmod_t id,
58 int start,
59 kmod_args_t *data,
60 mach_msg_type_number_t *dataCount);
61
62 extern kern_return_t kmod_retain(kmod_t id);
63 extern kern_return_t kmod_release(kmod_t id);
64
65 extern void flush_dcache(vm_offset_t addr, unsigned cnt, int phys);
66 extern void invalidate_icache(vm_offset_t addr, unsigned cnt, int phys);
67 };
68
69
70 #define LOG_DELAY()
71
72 #define VTYELLOW "\033[33m"
73 #define VTRESET "\033[0m"
74
75
76
77
78 /*********************************************************************
79 *
80 *********************************************************************/
81 bool verifyCompatibility(OSString * extName, OSString * requiredVersion)
82 {
83 OSDictionary * extensionsDict; // don't release
84 OSDictionary * extDict; // don't release
85 OSDictionary * extPlist; // don't release
86 OSString * extVersion; // don't release
87 OSString * extCompatVersion; // don't release
88 UInt32 ext_version;
89 UInt32 ext_compat_version;
90 UInt32 required_version;
91
92 /* Get the dictionary of startup extensions.
93 * This is keyed by module name.
94 */
95 extensionsDict = getStartupExtensions();
96 if (!extensionsDict) {
97 IOLog("verifyCompatibility(): No extensions dictionary.\n");
98 return false;
99 }
100
101 /* Get the requested extension's dictionary entry and its property
102 * list, containing module dependencies.
103 */
104 extDict = OSDynamicCast(OSDictionary,
105 extensionsDict->getObject(extName));
106
107 if (!extDict) {
108 IOLog("verifyCompatibility(): "
109 "Extension \"%s\" cannot be found.\n",
110 extName->getCStringNoCopy());
111 return false;
112 }
113
114 extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
115 if (!extPlist) {
116 IOLog("verifyCompatibility(): "
117 "Extension \"%s\" has no property list.\n",
118 extName->getCStringNoCopy());
119 return false;
120 }
121
122
123 extVersion = OSDynamicCast(OSString,
124 extPlist->getObject("CFBundleVersion"));
125 if (!extVersion) {
126 IOLog("verifyCompatibility(): "
127 "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
128 extName->getCStringNoCopy());
129 return false;
130 }
131
132 extCompatVersion = OSDynamicCast(OSString,
133 extPlist->getObject("OSBundleCompatibleVersion"));
134 if (!extCompatVersion) {
135 IOLog("verifyCompatibility(): "
136 "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
137 extName->getCStringNoCopy());
138 return false;
139 }
140
141 if (!VERS_parse_string(requiredVersion->getCStringNoCopy(),
142 &required_version)) {
143 IOLog("verifyCompatibility(): "
144 "Can't parse required version \"%s\" of dependency %s.\n",
145 requiredVersion->getCStringNoCopy(),
146 extName->getCStringNoCopy());
147 return false;
148 }
149 if (!VERS_parse_string(extVersion->getCStringNoCopy(),
150 &ext_version)) {
151 IOLog("verifyCompatibility(): "
152 "Can't parse version \"%s\" of dependency %s.\n",
153 extVersion->getCStringNoCopy(),
154 extName->getCStringNoCopy());
155 return false;
156 }
157 if (!VERS_parse_string(extCompatVersion->getCStringNoCopy(),
158 &ext_compat_version)) {
159 IOLog("verifyCompatibility(): "
160 "Can't parse compatible version \"%s\" of dependency %s.\n",
161 extCompatVersion->getCStringNoCopy(),
162 extName->getCStringNoCopy());
163 return false;
164 }
165
166 if (required_version > ext_version || required_version < ext_compat_version) {
167 return false;
168 }
169
170 return true;
171 }
172
173 /*********************************************************************
174 * This function builds a uniqued, in-order list of modules that need
175 * to be loaded in order for kmod_name to be successfully loaded. This
176 * list ends with kmod_name itself.
177 *********************************************************************/
178 static
179 OSArray * getDependencyListForKmod(const char * kmod_name) {
180
181 int error = 0;
182
183 OSDictionary * extensionsDict; // don't release
184 OSDictionary * extDict; // don't release
185 OSDictionary * extPlist; // don't release
186 OSString * extName; // don't release
187 OSArray * dependencyList = NULL; // return value, caller releases
188 OSBoolean * isKernelResourceObj = 0; // don't release
189 bool isKernelResource = false;
190 bool declaresExecutable = false;
191 unsigned int i;
192
193 /* These are used to remove duplicates from the dependency list.
194 */
195 OSArray * originalList = NULL; // must be released
196 OSDictionary * encounteredNames = NULL; // must be release
197
198
199 /* Get the dictionary of startup extensions.
200 * This is keyed by module name.
201 */
202 extensionsDict = getStartupExtensions();
203 if (!extensionsDict) {
204 IOLog("getDependencyListForKmod(): No extensions dictionary.\n");
205 LOG_DELAY();
206 error = 1;
207 goto finish;
208 }
209
210
211 /* Get the requested extension's dictionary entry and its property
212 * list, containing module dependencies.
213 */
214 extDict = OSDynamicCast(OSDictionary,
215 extensionsDict->getObject(kmod_name));
216
217 if (!extDict) {
218 IOLog("getDependencyListForKmod(): "
219 "Extension \"%s\" cannot be found.\n",
220 kmod_name);
221 LOG_DELAY();
222 error = 1;
223 goto finish;
224 }
225
226 extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
227 if (!extPlist) {
228 IOLog("getDependencyListForKmod(): "
229 "Extension \"%s\" has no property list.\n",
230 kmod_name);
231 LOG_DELAY();
232 error = 1;
233 goto finish;
234 }
235
236
237 /* Verify that the retrieved entry's "CFBundleIdentifier" property exists.
238 * This will be added to the dependency list.
239 */
240 extName = OSDynamicCast(OSString,
241 extPlist->getObject("CFBundleIdentifier"));
242 if (!extName) {
243 IOLog("getDependencyListForKmod(): "
244 "Extension \"%s\" has no \"CFBundleIdentifier\" property.\n",
245 kmod_name);
246 LOG_DELAY();
247 error = 1;
248 goto finish;
249 }
250
251 dependencyList = OSArray::withCapacity(10);
252 if (!dependencyList) {
253 IOLog("getDependencyListForKmod(): "
254 "Couldn't allocate dependency array for extension \"%s\".\n",
255 kmod_name);
256 LOG_DELAY();
257 error = 1;
258 goto finish;
259 }
260
261 /* A kext that's not a kernel extension and declares no executable has nothing
262 * to load, so just return an empty array.
263 */
264 isKernelResourceObj = OSDynamicCast(OSBoolean,
265 extPlist->getObject("OSKernelResource"));
266 if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
267 isKernelResource = true;
268 } else {
269 isKernelResource = false;
270 }
271
272 if (extPlist->getObject("CFBundleExecutable")) {
273 declaresExecutable = true;
274 } else {
275 declaresExecutable = false;
276 }
277
278 if (!isKernelResource && !declaresExecutable) {
279 error = 0;
280 goto finish;
281 }
282
283 /* Okay, let's get started.
284 */
285 dependencyList->setObject(extName);
286
287
288 /* Here's a slightly tricky bit. This loop iterates through
289 * the dependency list until it runs off the end. Each time
290 * through, however, any number of dependencies can be added
291 * to the end of the list. Eventually some extensions won't
292 * have any more dependencies, no more names will be added
293 * to the list, and this loop will terminate.
294 */
295 for (i = 0; i < dependencyList->getCount(); i++) {
296
297 // None of these needs to be released, as they're all from plists.
298 OSString * curName;
299 OSDictionary * curExtDict;
300 OSDictionary * curExtDepDict;
301 OSDictionary * curExtPlist;
302 OSString * curDepName;
303
304
305 /* An arbitrary limit to prevent infinite loops.
306 */
307 if (i > 255) {
308 IOLog("getDependencyListForKmod(): "
309 "max dependency list length exceeded for "
310 "extension \"%s\".\n",
311 kmod_name);
312 LOG_DELAY();
313 error = 1;
314 goto finish;
315 }
316
317 curName = OSDynamicCast(OSString, dependencyList->getObject(i));
318
319 curExtDict = OSDynamicCast(OSDictionary,
320 extensionsDict->getObject(curName));
321 if (!curExtDict) {
322 IOLog("getDependencyListForKmod(): "
323 "Extension \"%s\", required for extension \"%s\", "
324 "is not available.\n",
325 curName->getCStringNoCopy(), kmod_name);
326 LOG_DELAY();
327 error = 1;
328 goto finish;
329 }
330
331 curExtPlist = OSDynamicCast(OSDictionary,
332 curExtDict->getObject("plist"));
333 if (!curExtPlist) {
334 IOLog("getDependencyListForKmod(): "
335 "Extension \"%s\", required for extension \"%s\", "
336 "has no property list.\n",
337 curName->getCStringNoCopy(), kmod_name);
338 LOG_DELAY();
339 error = 1;
340 goto finish;
341 }
342
343 curExtDepDict = OSDynamicCast(OSDictionary,
344 curExtPlist->getObject("OSBundleLibraries"));
345 if (curExtDepDict) {
346 OSCollectionIterator * keyIterator =
347 OSCollectionIterator::withCollection(curExtDepDict);
348
349 if (!keyIterator) {
350 IOLog("getDependencyListForKmod(): "
351 "Couldn't allocate iterator for extension "
352 "\"%s\".\n", kmod_name);
353 LOG_DELAY();
354 error = 1;
355 goto finish;
356 }
357 while ( (curDepName =
358 OSDynamicCast(OSString,
359 keyIterator->getNextObject())) ) {
360
361 OSString * requiredVersion = OSDynamicCast(OSString,
362 curExtDepDict->getObject(curDepName));
363
364 if (!verifyCompatibility(curDepName, requiredVersion)) {
365 IOLog("getDependencyListForKmod(): "
366 "Dependency %s of %s is not compatible or is unavailable.\n",
367 curDepName->getCStringNoCopy(),
368 curName->getCStringNoCopy());
369 LOG_DELAY();
370 error = 1;
371 goto finish;
372 }
373
374 /* Don't add any entries that are not kernel resources and that declare no
375 * executable. Such kexts have nothing to load and so don't belong in the
376 * dependency list. Entries that are kernel resource *do* get added,
377 * however, because such kexts get fake kmod entries for reference counting.
378 */
379 isKernelResourceObj = OSDynamicCast(OSBoolean,
380 curExtPlist->getObject("OSKernelResource"));
381 if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
382 isKernelResource = true;
383 } else {
384 isKernelResource = false;
385 }
386 if (curExtPlist->getObject("CFBundleExecutable")) {
387 declaresExecutable = true;
388 } else {
389 declaresExecutable = false;
390 }
391
392 if (!isKernelResource && !declaresExecutable) {
393 continue;
394 }
395
396 dependencyList->setObject(curDepName);
397 }
398
399 keyIterator->release();
400 }
401 }
402
403
404 /*****
405 * The dependency list now exists in the reverse order of required loads,
406 * and may have duplicates. Now we turn the list around and remove
407 * duplicates.
408 */
409 originalList = dependencyList;
410 dependencyList = OSArray::withCapacity(originalList->getCount());
411 if (!dependencyList) {
412 IOLog("getDependenciesForKmod(): "
413 "Couldn't allocate reversal dependency list for extension "
414 "\"%s\".\n", kmod_name);
415 LOG_DELAY();
416 error = 1;
417 goto finish;
418 }
419 encounteredNames = OSDictionary::withCapacity(originalList->getCount());
420 if (!encounteredNames) {
421 IOLog("getDependenciesForKmod(): "
422 "Couldn't allocate list of encountered names for extension "
423 "\"%s\".\n", kmod_name);
424 LOG_DELAY();
425 error = 1;
426 goto finish;
427 }
428
429
430 /* Go backward through the original list, using the encounteredNames
431 * dictionary to check for duplicates. We put originalList in as the
432 * value because we need some non-NULL value.
433 */
434 i = originalList->getCount();
435
436 if (i > 0) {
437 do {
438 i--;
439
440 OSString * item = OSDynamicCast(OSString,
441 originalList->getObject(i));
442
443 if ( ! encounteredNames->getObject(item) ) {
444 encounteredNames->setObject(item, originalList);
445 dependencyList->setObject(item);
446 }
447 } while (i > 0);
448 }
449
450
451 finish:
452
453 if (originalList) {
454 originalList->release();
455 }
456 if (encounteredNames) {
457 encounteredNames->release();
458 }
459 if (error) {
460 if (dependencyList) {
461 dependencyList->release();
462 dependencyList = NULL;
463 }
464 }
465
466 return dependencyList;
467 }
468
469
470 /*********************************************************************
471 *********************************************************************/
472 /* Used in address_for_loaded_kmod.
473 */
474 static kmod_info_t * g_current_kmod_info = NULL;
475 static const char * g_current_kmod_name = NULL;
476
477 /* Globals to pass link buffer info from
478 * address_for_loaded_kmod() and alloc_for_kmod()
479 * to load_kmod().
480 *
481 * link_load_address is the address used to lay
482 * down the linked code. It gets adjusted by the
483 * pad between the headers size and a full page
484 * multiple. If an error occurs this gets set to
485 * zero so that the kld client code can detect
486 * an address or allocation error even if kld
487 * returns success.
488 *
489 * link_load_size is the size of the image as
490 * created by kld_load_from_memory(). link_buffer_size
491 * is the size of the buffer allocated for the final
492 * laid-down image, and is adjusted by rounding the
493 * load size and header size up to full-page multiples.
494 *
495 * link_buffer_address is set only by alloc_for_kmod();
496 * its value is used as a check if kld_load_from_memory()
497 * fails so that the buffer can be deallocated.
498 */
499 static unsigned long link_load_address = 0;
500 static unsigned long link_load_size = 0;
501 static unsigned long link_buffer_size = 0;
502 static unsigned long link_header_size = 0;
503 static unsigned long link_buffer_address = 0;
504
505
506 /*********************************************************************
507 * This function is registered before kmod_load_from_memory() is
508 * invoked to build symbol table entries for an already-loaded
509 * kmod. This function just checks the g_current_kmod_info variable
510 * to gets its load address, and futzes it by the header offset (pad).
511 * See lower comments for more info on load address futzing.
512 *********************************************************************/
513 static
514 unsigned long address_for_loaded_kmod(
515 unsigned long size,
516 unsigned long headers_size) {
517
518 unsigned long round_headers_size;
519 unsigned long headers_pad;
520
521 if (!g_current_kmod_info) {
522 IOLog("address_for_loaded_kmod(): No current kmod.\n");
523 LOG_DELAY();
524 link_load_address = 0; // error sentinel for kld client
525 return 0;
526 }
527
528 round_headers_size = round_page(headers_size);
529 headers_pad = round_headers_size - headers_size;
530
531 link_load_address = (unsigned long)g_current_kmod_info->address +
532 headers_pad;
533
534 return link_load_address;
535 }
536
537
538 /*********************************************************************
539 * This function is registered before kmod_load_from_memory() is
540 * invoked to actually load a new kmod. It rounds up the header and
541 * total sizes and vm_allocates a buffer for the kmod. Now, KLD doesn't
542 * enforce any alignment of headers or segments, and we want to make
543 * sure that the executable code of the kmod lies on a page boundary.
544 * to do so, this function figures the pad between the actual header
545 * size and the page-rounded header size, and returns that offset into
546 * the allocated buffer. After kmod_load_from_memory() returns, its
547 * caller will move the mach_header struct back to the beginning of the
548 * allocated buffer so that the kmod_info_t structure contains the
549 * correct address.
550 *********************************************************************/
551 static
552 unsigned long alloc_for_kmod(
553 unsigned long size,
554 unsigned long headers_size) {
555
556 vm_address_t buffer = 0;
557 kern_return_t k_result;
558
559 unsigned long round_headers_size;
560 unsigned long round_segments_size;
561 unsigned long round_size;
562 unsigned long headers_pad;
563
564 round_headers_size = round_page(headers_size);
565 round_segments_size = round_page(size - headers_size);
566 round_size = round_headers_size + round_segments_size;
567 headers_pad = round_headers_size - headers_size;
568
569 k_result = vm_allocate(kernel_map, (vm_offset_t *)&buffer,
570 round_size, TRUE);
571 if (k_result != KERN_SUCCESS) {
572 IOLog("alloc_for_kmod(): Can't allocate memory.\n");
573 LOG_DELAY();
574 link_buffer_address = 0; // make sure it's clear
575 link_load_address = 0; // error sentinel for kld client
576 return 0;
577 }
578
579 link_load_size = size;
580
581 link_buffer_address = buffer;
582 link_buffer_size = round_size;
583 link_header_size = headers_size; // NOT rounded!
584
585 link_load_address = link_buffer_address + headers_pad;
586
587 return link_load_address;
588 }
589
590 /*********************************************************************
591 * This function reads the startup extensions dictionary to get the
592 * address and length of the executable data for the requested kmod.
593 *********************************************************************/
594 static
595 int map_and_patch(const char * kmod_name) {
596
597 char *address;
598
599 // Does the kld system already know about this kmod?
600 address = (char *) kld_file_getaddr(kmod_name, NULL);
601 if (address)
602 return 1;
603
604 // None of these needs to be released.
605 OSDictionary * extensionsDict;
606 OSDictionary * kmodDict;
607 OSData * compressedCode = 0;
608
609 // Driver Code may need to be released
610 OSData * driverCode;
611
612 /* Get the requested kmod's info dictionary from the global
613 * startup extensions dictionary.
614 */
615 extensionsDict = getStartupExtensions();
616 if (!extensionsDict) {
617 IOLog("map_and_patch(): No extensions dictionary.\n");
618 LOG_DELAY();
619 return 0;
620 }
621
622 kmodDict = OSDynamicCast(OSDictionary,
623 extensionsDict->getObject(kmod_name));
624 if (!kmodDict) {
625 IOLog("map_and_patch(): "
626 "Extension \"%s\" cannot be found.\n", kmod_name);
627 LOG_DELAY();
628 return 0;
629 }
630
631 Boolean ret = false;
632
633 driverCode = OSDynamicCast(OSData, kmodDict->getObject("code"));
634 if (driverCode) {
635 ret = kld_file_map(kmod_name,
636 (unsigned char *) driverCode->getBytesNoCopy(),
637 (size_t) driverCode->getLength(),
638 /* isKmem */ false);
639 }
640 else { // May be an compressed extension
641
642 // If we have a compressed segment the uncompressModule
643 // will return a new OSData object that points to the kmem_alloced
644 // memory. Note we don't take a reference to driverCode so later
645 // when we release it we will actually free this driver. Ownership
646 // of the kmem has been handed of to kld_file.
647 compressedCode = OSDynamicCast(OSData,
648 kmodDict->getObject("compressedCode"));
649 if (!compressedCode) {
650 IOLog("map_and_patch(): "
651 "Extension \"%s\" has no \"code\" property.\n", kmod_name);
652 LOG_DELAY();
653 return 0;
654 }
655 if (!uncompressModule(compressedCode, &driverCode)) {
656 IOLog("map_and_patch(): "
657 "Extension \"%s\" Couldn't uncompress code.\n", kmod_name);
658 LOG_DELAY();
659 return 0;
660 }
661
662 unsigned char *driver = (unsigned char *) driverCode->getBytesNoCopy();
663 size_t driverSize = driverCode->getLength();
664
665 ret = kld_file_map(kmod_name, driver, driverSize, /* isKmem */ true);
666 driverCode->release();
667 if (!ret)
668 kmem_free(kernel_map, (vm_address_t) driver, driverSize);
669 }
670
671 if (!ret) {
672 IOLog("map_and_patch(): "
673 "Extension \"%s\" Didn't successfully load.\n", kmod_name);
674 LOG_DELAY();
675 return 0;
676 }
677
678 ret = TRUE;
679 if (!kld_file_patch_OSObjects(kmod_name)) {
680 IOLog("map_and_patch(): "
681 "Extension \"%s\" Error binding OSObjects.\n", kmod_name);
682 LOG_DELAY();
683
684 // RY: Instead of returning here, set the return value.
685 // We still need to call kld_file_prepare_for_link because
686 // we might have patched files outside of the driver. Don't
687 // worry, it will know to ignore the damaged file
688 ret = FALSE;
689 }
690
691 // Now repair any damage that the kld patcher may have done to the image
692 kld_file_prepare_for_link();
693
694 return ret;
695 }
696
697 /*********************************************************************
698 *********************************************************************/
699 bool stamp_kmod(const char * kmod_name, kmod_info_t * kmod_info) {
700 bool result = false;
701 OSDictionary * extensionsDict = NULL; // don't release
702 OSDictionary * kmodDict = NULL; // don't release
703 OSDictionary * plist = NULL; // don't release
704 OSString * versionString = NULL; // don't release
705 const char * plist_version = NULL; // don't free
706
707 if (strlen(kmod_name) + 1 > KMOD_MAX_NAME) {
708 IOLog("stamp_kmod(): Kext identifier \"%s\" is too long.\n",
709 kmod_name);
710 LOG_DELAY();
711 result = false;
712 goto finish;
713 }
714
715 strcpy(kmod_info->name, kmod_name);
716
717 /* Get the dictionary of startup extensions.
718 * This is keyed by module name.
719 */
720 extensionsDict = getStartupExtensions();
721 if (!extensionsDict) {
722 IOLog("stamp_kmod(): No extensions dictionary.\n");
723 LOG_DELAY();
724 result = false;
725 goto finish;
726 }
727
728 kmodDict = OSDynamicCast(OSDictionary,
729 extensionsDict->getObject(kmod_name));
730 if (!kmodDict) {
731 IOLog("stamp_kmod(): Can't find record for kmod \"%s\".\n",
732 kmod_name);
733 LOG_DELAY();
734 result = false;
735 goto finish;
736 }
737
738 plist = OSDynamicCast(OSDictionary,
739 kmodDict->getObject("plist"));
740 if (!kmodDict) {
741 IOLog("stamp_kmod(): Kmod \"%s\" has no property list.\n",
742 kmod_name);
743 LOG_DELAY();
744 result = false;
745 goto finish;
746 }
747
748 /*****
749 * Get the kext's version and stuff it into the kmod. This used
750 * to be a check that the kext & kmod had the same version, but
751 * now we just overwrite the kmod's version.
752 */
753
754 versionString = OSDynamicCast(OSString,
755 plist->getObject("CFBundleVersion"));
756 if (!versionString) {
757 IOLog("stamp_kmod(): Kmod \"%s\" has no \"CFBundleVersion\" "
758 "property.\n",
759 kmod_name);
760 LOG_DELAY();
761 result = false;
762 goto finish;
763 }
764
765 plist_version = versionString->getCStringNoCopy();
766 if (!plist_version) {
767 IOLog("stamp_kmod(): Can't get C string for kext version.\n");
768 LOG_DELAY();
769 result = false;
770 goto finish;
771 }
772
773 if (strlen(plist_version) + 1 > KMOD_MAX_NAME) {
774 IOLog("stamp_kmod(): Version \"%s\" of kext \"%s\" is too long.\n",
775 plist_version, kmod_name);
776 LOG_DELAY();
777 result = false;
778 goto finish;
779 }
780
781 strcpy(kmod_info->version, plist_version);
782
783 result = true;
784
785 finish:
786
787 return result;
788 }
789
790
791 /*********************************************************************
792 * This function takes a dependency list containing a series of
793 * already-loaded module names, followed by a single name for a module
794 * that hasn't yet been loaded. It invokes kld_load_from_memory() to
795 * build symbol info for the already-loaded modules, and then finally
796 * loads the actually requested module.
797 *********************************************************************/
798 static
799 kern_return_t load_kmod(OSArray * dependencyList) {
800 kern_return_t result = KERN_SUCCESS;
801
802 unsigned int num_dependencies = 0;
803 kmod_info_t ** kmod_dependencies = NULL;
804 unsigned int i;
805 OSString * requestedKmodName; // don't release
806 const char * requested_kmod_name;
807 OSString * currentKmodName; // don't release
808 char * kmod_address;
809 unsigned long kmod_size;
810 struct mach_header * kmod_header;
811 unsigned long kld_result;
812 int do_kld_unload = 0;
813 kmod_info_t * kmod_info_freeme = 0;
814 kmod_info_t * kmod_info = 0;
815 kmod_t kmod_id;
816
817
818 /* Separate the requested kmod from its dependencies.
819 */
820 i = dependencyList->getCount();
821 if (i == 0) {
822 IOLog("load_kmod(): Called with empty list.\n");
823 LOG_DELAY();
824 result = KERN_FAILURE;
825 goto finish;
826 } else {
827 i--; // make i be the index of the last entry
828 }
829
830 requestedKmodName = OSDynamicCast(OSString, dependencyList->getObject(i));
831 if (!requestedKmodName) {
832 IOLog("load_kmod(): Called with invalid list of kmod names.\n");
833 LOG_DELAY();
834 result = KERN_FAILURE;
835 goto finish;
836 }
837 requested_kmod_name = requestedKmodName->getCStringNoCopy();
838 dependencyList->removeObject(i);
839
840 /* If the requested kmod is already loaded, there's no work to do.
841 */
842 kmod_info_freeme = kmod_lookupbyname_locked(requested_kmod_name);
843 if (kmod_info_freeme) {
844 // FIXME: Need to check for version mismatch if already loaded.
845 result = KERN_SUCCESS;
846 goto finish;
847 }
848
849
850 /* Do the KLD loads for the already-loaded modules in order to get
851 * their symbols.
852 */
853 kld_address_func(&address_for_loaded_kmod);
854
855 num_dependencies = dependencyList->getCount();
856 kmod_dependencies = (kmod_info_t **)kalloc(num_dependencies *
857 sizeof(kmod_info_t *));
858 if (!kmod_dependencies) {
859 IOLog("load_kmod(): Failed to allocate memory for dependency array "
860 "during load of kmod \"%s\".\n", requested_kmod_name);
861 LOG_DELAY();
862 result = KERN_FAILURE;
863 goto finish;
864 }
865
866 bzero(kmod_dependencies, num_dependencies *
867 sizeof(kmod_info_t *));
868
869 for (i = 0; i < num_dependencies; i++) {
870
871 currentKmodName = OSDynamicCast(OSString,
872 dependencyList->getObject(i));
873
874 if (!currentKmodName) {
875 IOLog("load_kmod(): Invalid dependency name at index %d for "
876 "kmod \"%s\".\n", i, requested_kmod_name);
877 LOG_DELAY();
878 result = KERN_FAILURE;
879 goto finish;
880 }
881
882 const char * current_kmod_name = currentKmodName->getCStringNoCopy();
883
884 // These globals are needed by the kld_address functions
885 g_current_kmod_info = kmod_lookupbyname_locked(current_kmod_name);
886 g_current_kmod_name = current_kmod_name;
887
888 if (!g_current_kmod_info) {
889 IOLog("load_kmod(): Missing dependency \"%s\".\n",
890 current_kmod_name);
891 LOG_DELAY();
892 result = KERN_FAILURE;
893 goto finish;
894 }
895
896 /* Record the current kmod as a dependency of the requested
897 * one. This will be used in building references after the
898 * load is complete.
899 */
900 kmod_dependencies[i] = g_current_kmod_info;
901
902 /* If the current kmod's size is zero it means that we have a
903 * fake in-kernel dependency. If so then don't have to arrange
904 * for its symbol table to be reloaded as it is
905 * part of the kernel's symbol table..
906 */
907 if (!g_current_kmod_info->size)
908 continue;
909
910 if (!kld_file_merge_OSObjects(current_kmod_name)) {
911 IOLog("load_kmod(): Can't merge OSObjects \"%s\".\n",
912 current_kmod_name);
913 LOG_DELAY();
914 result = KERN_FAILURE;
915 goto finish;
916 }
917
918 kmod_address = (char *)
919 kld_file_getaddr(current_kmod_name, (long *) &kmod_size);
920 if (!kmod_address) {
921
922 IOLog("load_kmod() failed for dependency kmod "
923 "\"%s\".\n", current_kmod_name);
924 LOG_DELAY();
925 result = KERN_FAILURE;
926 goto finish;
927 }
928
929 kld_result = kld_load_from_memory(&kmod_header,
930 current_kmod_name, kmod_address, kmod_size);
931
932 if (kld_result) {
933 do_kld_unload = 1;
934 }
935
936 if (!kld_result || !link_load_address) {
937 IOLog("kld_load_from_memory() failed for dependency kmod "
938 "\"%s\".\n", current_kmod_name);
939 LOG_DELAY();
940 result = KERN_FAILURE;
941 goto finish;
942 }
943
944 kld_forget_symbol("_kmod_info");
945 }
946
947 /*****
948 * Now that we've done all the dependencies, which should have already
949 * been loaded, we do the last requested module, which should not have
950 * already been loaded.
951 */
952 kld_address_func(&alloc_for_kmod);
953
954 g_current_kmod_name = requested_kmod_name;
955 g_current_kmod_info = 0; // there is no kmod yet
956
957 if (!map_and_patch(requested_kmod_name)) {
958 IOLog("load_kmod: map_and_patch() failed for "
959 "kmod \"%s\".\n", requested_kmod_name);
960 LOG_DELAY();
961 result = KERN_FAILURE;
962 goto finish;
963 }
964
965 kmod_address = (char *)
966 kld_file_getaddr(requested_kmod_name, (long *) &kmod_size);
967 if (!kmod_address) {
968 IOLog("load_kmod: kld_file_getaddr() failed internal error "
969 "on \"%s\".\n", requested_kmod_name);
970 LOG_DELAY();
971 result = KERN_FAILURE;
972 goto finish;
973 }
974
975 kld_result = kld_load_from_memory(&kmod_header,
976 requested_kmod_name, kmod_address, kmod_size);
977
978 if (kld_result) {
979 do_kld_unload = 1;
980 }
981
982 if (!kld_result || !link_load_address) {
983 IOLog("load_kmod(): kld_load_from_memory() failed for "
984 "kmod \"%s\".\n", requested_kmod_name);
985 LOG_DELAY();
986 result = KERN_FAILURE;
987 goto finish;
988 }
989
990
991 /* Copy the linked header and image into the vm_allocated buffer.
992 * Move each onto the appropriate page-aligned boundary as given
993 * by the global link_... variables.
994 */
995 bzero((char *)link_buffer_address, link_buffer_size);
996 // bcopy() is (from, to, length)
997 bcopy((char *)kmod_header, (char *)link_buffer_address, link_header_size);
998 bcopy((char *)kmod_header + link_header_size,
999 (char *)link_buffer_address + round_page(link_header_size),
1000 link_load_size - link_header_size);
1001
1002
1003 /* Get the kmod_info struct for the newly-loaded kmod.
1004 */
1005 if (!kld_lookup("_kmod_info", (unsigned long *)&kmod_info)) {
1006 IOLog("kld_lookup() of \"_kmod_info\" failed for "
1007 "kmod \"%s\".\n", requested_kmod_name);
1008 LOG_DELAY();
1009 result = KERN_FAILURE;
1010 goto finish;
1011 }
1012
1013
1014 if (!stamp_kmod(requested_kmod_name, kmod_info)) {
1015 // stamp_kmod() logs a meaningful message
1016 result = KERN_FAILURE;
1017 goto finish;
1018 }
1019
1020
1021 /* kld_lookup of _kmod_info yielded the actual linked address,
1022 * so now that we've copied the data into its real place,
1023 * we can set this stuff.
1024 */
1025 kmod_info->address = link_buffer_address;
1026 kmod_info->size = link_buffer_size;
1027 kmod_info->hdr_size = round_page(link_header_size);
1028
1029 /* We've written data and instructions, so *flush* the data cache
1030 * and *invalidate* the instruction cache.
1031 */
1032 flush_dcache(link_buffer_address, link_buffer_size, false);
1033 invalidate_icache(link_buffer_address, link_buffer_size, false);
1034
1035
1036 /* Register the new kmod with the kernel proper.
1037 */
1038 if (kmod_create_internal(kmod_info, &kmod_id) != KERN_SUCCESS) {
1039 IOLog("load_kmod(): kmod_create() failed for "
1040 "kmod \"%s\".\n", requested_kmod_name);
1041 LOG_DELAY();
1042 result = KERN_FAILURE;
1043 goto finish;
1044 }
1045
1046 #if DEBUG
1047 IOLog("kmod id %d successfully created at 0x%lx, size %ld.\n",
1048 (unsigned int)kmod_id, link_buffer_address, link_buffer_size);
1049 LOG_DELAY();
1050 #endif DEBUG
1051
1052 /* Record dependencies for the newly-loaded kmod.
1053 */
1054 for (i = 0; i < num_dependencies; i++) {
1055 kmod_info_t * cur_dependency_info;
1056 kmod_t packed_id;
1057 cur_dependency_info = kmod_dependencies[i];
1058 packed_id = KMOD_PACK_IDS(kmod_id, cur_dependency_info->id);
1059 if (kmod_retain(packed_id) != KERN_SUCCESS) {
1060 IOLog("load_kmod(): kmod_retain() failed for "
1061 "kmod \"%s\".\n", requested_kmod_name);
1062 LOG_DELAY();
1063 kmod_destroy_internal(kmod_id);
1064 result = KERN_FAILURE;
1065 goto finish;
1066 }
1067 }
1068
1069 /* Start the kmod (which invokes constructors for I/O Kit
1070 * drivers.
1071 */
1072 // kmod_start_or_stop(id, start?, user data, datalen)
1073 if (kmod_start_or_stop(kmod_id, 1, 0, 0) != KERN_SUCCESS) {
1074 IOLog("load_kmod(): kmod_start_or_stop() failed for "
1075 "kmod \"%s\".\n", requested_kmod_name);
1076 LOG_DELAY();
1077 kmod_destroy_internal(kmod_id);
1078 result = KERN_FAILURE;
1079 goto finish;
1080 }
1081
1082 finish:
1083
1084 if (kmod_info_freeme) {
1085 kfree(kmod_info_freeme, sizeof(kmod_info_t));
1086 }
1087
1088 /* Only do a kld_unload_all() if at least one load happened.
1089 */
1090 if (do_kld_unload) {
1091 kld_unload_all(/* deallocate sets */ 1);
1092 }
1093
1094 /* If the link failed, blow away the allocated link buffer.
1095 */
1096 if (result != KERN_SUCCESS && link_buffer_address) {
1097 vm_deallocate(kernel_map, link_buffer_address, link_buffer_size);
1098 }
1099
1100 if (kmod_dependencies) {
1101 for (i = 0; i < num_dependencies; i++) {
1102 if (kmod_dependencies[i]) {
1103 kfree(kmod_dependencies[i], sizeof(kmod_info_t));
1104 }
1105 }
1106 kfree((unsigned int)kmod_dependencies,
1107 num_dependencies * sizeof(kmod_info_t *));
1108 }
1109
1110 /* Reset these static global variables for the next call.
1111 */
1112 g_current_kmod_name = NULL;
1113 g_current_kmod_info = NULL;
1114 link_buffer_address = 0;
1115 link_load_address = 0;
1116 link_load_size = 0;
1117 link_buffer_size = 0;
1118 link_header_size = 0;
1119
1120 return result;
1121 }
1122
1123
1124 /*********************************************************************
1125 * This is the function that IOCatalogue calls in order to load a kmod.
1126 * It first checks whether the kmod is already loaded. If the kmod
1127 * isn't loaded, this function builds a dependency list and calls
1128 * load_kmod() repeatedly to guarantee that each dependency is in fact
1129 * loaded.
1130 *********************************************************************/
1131 __private_extern__
1132 kern_return_t load_kernel_extension(char * kmod_name) {
1133 kern_return_t result = KERN_SUCCESS;
1134 kmod_info_t * kmod_info = 0; // must free
1135 OSArray * dependencyList = NULL; // must release
1136 OSArray * curDependencyList = NULL; // must release
1137
1138 /* See if the kmod is already loaded.
1139 */
1140 kmod_info = kmod_lookupbyname_locked(kmod_name);
1141 if (kmod_info) { // NOT checked
1142 result = KERN_SUCCESS;
1143 goto finish;
1144 }
1145
1146 /* It isn't loaded; build a dependency list and
1147 * load those.
1148 */
1149 unsigned int count;
1150 unsigned int i;
1151 dependencyList = getDependencyListForKmod(kmod_name);
1152 if (!dependencyList) {
1153 IOLog("load_kernel_extension(): "
1154 "Can't get dependencies for kernel extension \"%s\".\n",
1155 kmod_name);
1156 LOG_DELAY();
1157 result = KERN_FAILURE;
1158 goto finish;
1159 }
1160
1161 count = dependencyList->getCount();
1162 for (i = 0; i < count; i++) {
1163 kern_return_t load_result;
1164 OSString * curKmodName; // don't release
1165 const char * cur_kmod_name;
1166
1167 curKmodName = OSDynamicCast(OSString,
1168 dependencyList->getObject(i));
1169 cur_kmod_name = curKmodName->getCStringNoCopy();
1170 curDependencyList = getDependencyListForKmod(cur_kmod_name);
1171 if (!curDependencyList) {
1172 IOLog("load_kernel_extension(): "
1173 "Can't get dependencies for kernel extension \"%s\".\n",
1174 cur_kmod_name);
1175 LOG_DELAY();
1176 result = KERN_FAILURE;
1177 goto finish;
1178 } else {
1179 load_result = load_kmod(curDependencyList);
1180 if (load_result != KERN_SUCCESS) {
1181 IOLog("load_kernel_extension(): "
1182 "load_kmod() failed for kmod \"%s\".\n",
1183 cur_kmod_name);
1184 LOG_DELAY();
1185 result = load_result;
1186 goto finish;
1187 }
1188 curDependencyList->release();
1189 curDependencyList = NULL;
1190 }
1191 }
1192
1193
1194 finish:
1195
1196 if (kmod_info) {
1197 kfree(kmod_info, sizeof(kmod_info_t));
1198 }
1199
1200 if (dependencyList) {
1201 dependencyList->release();
1202 dependencyList = NULL;
1203 }
1204 if (curDependencyList) {
1205 curDependencyList->release();
1206 curDependencyList = NULL;
1207 }
1208
1209 return result;
1210 }