1 /*
2 * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1998 Apple Inc. All rights reserved.
30 *
31 * HISTORY
32 *
33 */
34 /*
35 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
36 * support for mandatory and extensible security protections. This notice
37 * is included in support of clause 2.2 (b) of the Apple Public License,
38 * Version 2.0.
39 */
40
41 #define IOKIT_ENABLE_SHARED_PTR
42
43 extern "C" {
44 #include <libkern/kernel_mach_header.h>
45 #include <kern/host.h>
46 #include <security/mac_data.h>
47 };
48
49 #include <machine/machine_routines.h>
50 #include <libkern/c++/OSContainers.h>
51 #include <libkern/c++/OSUnserialize.h>
52 #include <libkern/c++/OSKext.h>
53 #include <libkern/c++/OSSharedPtr.h>
54 #include <libkern/OSKextLibPrivate.h>
55 #include <libkern/OSDebug.h>
56
57 #include <IOKit/IODeviceTreeSupport.h>
58 #include <IOKit/IOService.h>
59 #include <IOKit/IOCatalogue.h>
60
61 #include <IOKit/IOLib.h>
62 #include <IOKit/assert.h>
63 #include <IOKit/IOKitKeysPrivate.h>
64
65 #if PRAGMA_MARK
66 #pragma mark Internal Declarations
67 #endif
68 /*********************************************************************
69 *********************************************************************/
70
71 OSSharedPtr<IOCatalogue> gIOCatalogue;
72 OSSharedPtr<const OSSymbol> gIOClassKey;
73 OSSharedPtr<const OSSymbol> gIOProbeScoreKey;
74 OSSharedPtr<const OSSymbol> gIOModuleIdentifierKey;
75 OSSharedPtr<const OSSymbol> gIOModuleIdentifierKernelKey;
76 OSSharedPtr<const OSSymbol> gIOHIDInterfaceClassName;
77 IORWLock * gIOCatalogLock;
78
79 #if PRAGMA_MARK
80 #pragma mark Utility functions
81 #endif
82
83 #if PRAGMA_MARK
84 #pragma mark IOCatalogue class implementation
85 #endif
86 /*********************************************************************
87 *********************************************************************/
88
89 #define super OSObject
90 OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
91
92 static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
93 OSDictionary *theModuleDict);
94
95
96 /*********************************************************************
97 *********************************************************************/
98 void
initialize(void)99 IOCatalogue::initialize(void)
100 {
101 OSSharedPtr<OSArray> array;
102 OSSharedPtr<OSString> errorString;
103 bool rc;
104
105 extern const char * gIOKernelConfigTables;
106
107 array = OSDynamicPtrCast<OSArray>(OSUnserialize(gIOKernelConfigTables, errorString));
108 if (!array && errorString) {
109 IOLog("KernelConfigTables syntax error: %s\n",
110 errorString->getCStringNoCopy());
111 }
112
113 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
114 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
115 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey );
116 gIOModuleIdentifierKernelKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKernelKey );
117 gIOHIDInterfaceClassName = OSSymbol::withCStringNoCopy( "IOHIDInterface" );
118
119
120 assert( array && gIOClassKey && gIOProbeScoreKey
121 && gIOModuleIdentifierKey);
122
123 gIOCatalogue = OSMakeShared<IOCatalogue>();
124 assert(gIOCatalogue);
125 rc = gIOCatalogue->init(array.get());
126 assert(rc);
127 }
128
129 /*********************************************************************
130 * Initialize the IOCatalog object.
131 *********************************************************************/
132 OSArray *
arrayForPersonality(OSDictionary * dict)133 IOCatalogue::arrayForPersonality(OSDictionary * dict)
134 {
135 const OSSymbol * sym;
136
137 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
138 if (!sym) {
139 return NULL;
140 }
141
142 return (OSArray *) personalities->getObject(sym);
143 }
144
145 void
addPersonality(OSDictionary * dict)146 IOCatalogue::addPersonality(OSDictionary * dict)
147 {
148 const OSSymbol * sym;
149 OSArray * arr;
150
151 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
152 if (!sym) {
153 return;
154 }
155 arr = (OSArray *) personalities->getObject(sym);
156 if (arr) {
157 arr->setObject(dict);
158 } else {
159 OSSharedPtr<OSArray> sharedArr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
160 personalities->setObject(sym, sharedArr.get());
161 }
162 }
163
164 /*********************************************************************
165 * Initialize the IOCatalog object.
166 *********************************************************************/
167 bool
init(OSArray * initArray)168 IOCatalogue::init(OSArray * initArray)
169 {
170 OSDictionary * dict;
171 OSObject * obj;
172
173 if (!super::init()) {
174 return false;
175 }
176
177 generation = 1;
178
179 personalities = OSDictionary::withCapacity(32);
180 personalities->setOptions(OSCollection::kSort, OSCollection::kSort);
181 for (unsigned int idx = 0; (obj = initArray->getObject(idx)); idx++) {
182 dict = OSDynamicCast(OSDictionary, obj);
183 if (!dict) {
184 continue;
185 }
186 OSKext::uniquePersonalityProperties(dict);
187 if (NULL == dict->getObject( gIOClassKey.get())) {
188 IOLog("Missing or bad \"%s\" key\n",
189 gIOClassKey->getCStringNoCopy());
190 continue;
191 }
192 dict->setObject("KernelConfigTable", kOSBooleanTrue);
193 addPersonality(dict);
194 }
195
196 gIOCatalogLock = IORWLockAlloc();
197 lock = gIOCatalogLock;
198
199 return true;
200 }
201
202 /*********************************************************************
203 * Release all resources used by IOCatalogue and deallocate.
204 * This will probably never be called.
205 *********************************************************************/
206 void
free(void)207 IOCatalogue::free( void )
208 {
209 panic("");
210 }
211
212 /*********************************************************************
213 *********************************************************************/
214 OSPtr<OSOrderedSet>
findDrivers(IOService * service,SInt32 * generationCount)215 IOCatalogue::findDrivers(
216 IOService * service,
217 SInt32 * generationCount)
218 {
219 OSDictionary * nextTable;
220 OSSharedPtr<OSOrderedSet> set;
221 OSArray * array;
222 const OSMetaClass * meta;
223 unsigned int idx;
224
225 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
226 (void *)(gIOProbeScoreKey.get()));
227 if (!set) {
228 return NULL;
229 }
230
231 IORWLockRead(lock);
232
233 meta = service->getMetaClass();
234 while (meta) {
235 array = (OSArray *) personalities->getObject(meta->getClassNameSymbol());
236 if (array) {
237 for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++) {
238 set->setObject(nextTable);
239 }
240 }
241 if (meta == &IOService::gMetaClass) {
242 break;
243 }
244 meta = meta->getSuperClass();
245 }
246
247 *generationCount = getGenerationCount();
248
249 IORWLockUnlock(lock);
250
251 return set;
252 }
253
254 /*********************************************************************
255 * Is personality already in the catalog?
256 *********************************************************************/
257 OSPtr<OSOrderedSet>
findDrivers(OSDictionary * matching,SInt32 * generationCount)258 IOCatalogue::findDrivers(
259 OSDictionary * matching,
260 SInt32 * generationCount)
261 {
262 OSSharedPtr<OSCollectionIterator> iter;
263 OSDictionary * dict;
264 OSSharedPtr<OSOrderedSet> set;
265 OSArray * array;
266 const OSSymbol * key;
267 unsigned int idx;
268
269 OSKext::uniquePersonalityProperties(matching);
270
271 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
272 (void *)(gIOProbeScoreKey.get()));
273 if (!set) {
274 return NULL;
275 }
276 iter = OSCollectionIterator::withCollection(personalities.get());
277 if (!iter) {
278 return nullptr;
279 }
280
281 IORWLockRead(lock);
282 while ((key = (const OSSymbol *) iter->getNextObject())) {
283 array = (OSArray *) personalities->getObject(key);
284 if (array) {
285 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
286 /* This comparison must be done with only the keys in the
287 * "matching" dict to enable general searches.
288 */
289 if (dict->isEqualTo(matching, matching)) {
290 set->setObject(dict);
291 }
292 }
293 }
294 }
295 *generationCount = getGenerationCount();
296 IORWLockUnlock(lock);
297
298 return set;
299 }
300
301 /*********************************************************************
302 * Add driver config tables to catalog and start matching process.
303 *
304 * Important that existing personalities are kept (not replaced)
305 * if duplicates found. Personalities can come from OSKext objects
306 * or from userland kext library. We want to minimize distinct
307 * copies between OSKext & IOCatalogue.
308 *
309 * xxx - userlib used to refuse to send personalities with IOKitDebug
310 * xxx - during safe boot. That would be better implemented here.
311 *********************************************************************/
312
313 bool
addDrivers(OSArray * drivers,bool doNubMatching)314 IOCatalogue::addDrivers(
315 OSArray * drivers,
316 bool doNubMatching)
317 {
318 bool result = false;
319 OSSharedPtr<OSOrderedSet> set;
320 OSSharedPtr<OSCollectionIterator> iter;
321 OSObject * object = NULL; // do not release
322 OSArray * persons = NULL;// do not release
323
324 persons = OSDynamicCast(OSArray, drivers);
325 if (!persons) {
326 goto finish;
327 }
328
329 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
330 (void *)(gIOProbeScoreKey.get()));
331 if (!set) {
332 goto finish;
333 }
334
335 iter = OSCollectionIterator::withCollection(persons);
336 if (!iter) {
337 goto finish;
338 }
339
340 /* Start with success; clear it on an error.
341 */
342 result = true;
343
344 IORWLockWrite(lock);
345 while ((object = iter->getNextObject())) {
346 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
347
348 OSDictionary * personality = OSDynamicCast(OSDictionary, object);
349
350 SInt count;
351
352 if (!personality) {
353 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
354 result = false;
355 break;
356 }
357
358 OSKext::uniquePersonalityProperties(personality);
359
360 // Add driver personality to catalogue.
361
362 OSArray * array = arrayForPersonality(personality);
363 if (!array) {
364 addPersonality(personality);
365 } else {
366 count = array->getCount();
367 while (count--) {
368 OSDictionary * driver;
369
370 // Be sure not to double up on personalities.
371 driver = (OSDictionary *)array->getObject(count);
372
373 /* Unlike in other functions, this comparison must be exact!
374 * The catalogue must be able to contain personalities that
375 * are proper supersets of others.
376 * Do not compare just the properties present in one driver
377 * personality or the other.
378 */
379 if (personality->isEqualTo(driver)) {
380 break;
381 }
382 }
383 if (count >= 0) {
384 // its a dup
385 continue;
386 }
387 result = array->setObject(personality);
388 if (!result) {
389 break;
390 }
391 }
392
393 set->setObject(personality);
394 }
395 // Start device matching.
396 if (result && doNubMatching && (set->getCount() > 0)) {
397 IOService::catalogNewDrivers(set.get());
398 generation++;
399 }
400 IORWLockUnlock(lock);
401
402 finish:
403
404 return result;
405 }
406
407 bool
408 IOCatalogue::removeDrivers(bool doNubMatching, bool (^shouldRemove)(OSDictionary *personality))
409 {
410 OSSharedPtr<OSOrderedSet> set;
411 OSSharedPtr<OSCollectionIterator> iter;
412 OSDictionary * dict;
413 OSArray * array;
414 const OSSymbol * key;
415 unsigned int idx;
416
417 set = OSOrderedSet::withCapacity(10,
418 IOServiceOrdering,
419 (void *)(gIOProbeScoreKey.get()));
420 if (!set) {
421 return false;
422 }
423 iter = OSCollectionIterator::withCollection(personalities.get());
424 if (!iter) {
425 return false;
426 }
427
428 IORWLockWrite(lock);
429 while ((key = (const OSSymbol *) iter->getNextObject())) {
430 array = (OSArray *) personalities->getObject(key);
431 if (array) {
432 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
433 if (shouldRemove(dict)) {
434 set->setObject(dict);
435 array->removeObject(idx);
436 idx--;
437 }
438 }
439 }
440 // Start device matching.
441 if (doNubMatching && (set->getCount() > 0)) {
442 IOService::catalogNewDrivers(set.get());
443 generation++;
444 }
445 }
446 IORWLockUnlock(lock);
447
448 return true;
449 }
450
451 /*********************************************************************
452 * Remove drivers from the catalog which match the
453 * properties in the matching dictionary.
454 *********************************************************************/
455 bool
removeDrivers(OSDictionary * matching,bool doNubMatching)456 IOCatalogue::removeDrivers(
457 OSDictionary * matching,
458 bool doNubMatching)
459 {
460 if (!matching) {
461 return false;
462 }
463 return removeDrivers(doNubMatching, ^(OSDictionary *dict) {
464 /* This comparison must be done with only the keys in the
465 * "matching" dict to enable general searches.
466 */
467 return dict->isEqualTo(matching, matching);
468 });
469 }
470
471 // Return the generation count.
472 SInt32
getGenerationCount(void) const473 IOCatalogue::getGenerationCount(void) const
474 {
475 return generation;
476 }
477 /*********************************************************************
478 *********************************************************************/
479 /* static */
480
481 bool
personalityIsBoot(OSDictionary * match)482 IOCatalogue::personalityIsBoot(OSDictionary * match)
483 {
484 OSString * moduleName;
485 OSSharedPtr<OSKext> theKext;
486
487 moduleName = OSDynamicCast(OSString, match->getObject(gIOModuleIdentifierKey.get()));
488 if (!moduleName) {
489 return true;
490 }
491 theKext = OSKext::lookupKextWithIdentifier(moduleName->getCStringNoCopy());
492 if (!theKext) {
493 return true;
494 }
495 switch (theKext->kc_type) {
496 case KCKindPrimary:
497 return true;
498 case KCKindUnknown:
499 return true;
500 case KCKindNone:
501 return false;
502 case KCKindAuxiliary:
503 return false;
504 case KCKindPageable:
505 return false;
506 default:
507 assert(false);
508 return false;
509 }
510 }
511
512 // Check to see if kernel module has been loaded already, and request its load.
513 bool
isModuleLoaded(OSDictionary * driver,OSObject ** kextRef) const514 IOCatalogue::isModuleLoaded(OSDictionary * driver, OSObject ** kextRef) const
515 {
516 OSString * moduleName = NULL;
517 OSString * publisherName = NULL;
518 OSReturn ret;
519
520 if (kextRef) {
521 *kextRef = NULL;
522 }
523 if (!driver) {
524 return false;
525 }
526
527 /* The personalities of codeless kexts often contain the bundle ID of the
528 * kext they reference, and not the bundle ID of the codeless kext itself.
529 * The prelinked kernel needs to know the bundle ID of the codeless kext
530 * so it can include these personalities, so OSKext stores that bundle ID
531 * in the IOPersonalityPublisher key, and we record it as requested here.
532 */
533 publisherName = OSDynamicCast(OSString,
534 driver->getObject(kIOPersonalityPublisherKey));
535 OSKext::recordIdentifierRequest(publisherName);
536
537 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKernelKey.get()));
538 if (moduleName) {
539 ret = OSKext::loadKextWithIdentifier(moduleName, kextRef);
540 if (kOSKextReturnDeferred == ret) {
541 // a request has been queued but the module isn't necessarily
542 // loaded yet, so stall.
543 return false;
544 }
545 OSString *moduleDextName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey.get()));
546 if (moduleDextName && !(moduleName->isEqualTo(moduleDextName))) {
547 OSSharedPtr<OSObject> dextRef;
548 ret = OSKext::loadKextWithIdentifier(moduleDextName, dextRef);
549 }
550 // module is present or never will be
551 return true;
552 }
553
554 /* If a personality doesn't hold the "CFBundleIdentifier" or "CFBundleIdentifierKernel" key
555 * it is assumed to be an "in-kernel" driver.
556 */
557 return true;
558 }
559
560 bool
isModuleLoaded(OSDictionary * driver,OSSharedPtr<OSObject> & kextRef) const561 IOCatalogue::isModuleLoaded(OSDictionary * driver, OSSharedPtr<OSObject>& kextRef) const
562 {
563 OSObject* kextRefRaw = NULL;
564 bool result = isModuleLoaded(driver, &kextRefRaw);
565 kextRef.reset(kextRefRaw, OSNoRetain);
566 return result;
567 }
568
569 /* This function is called after a module has been loaded.
570 * Is invoked from user client call, ultimately from IOKitLib's
571 * IOCatalogueModuleLoaded(). Sent from kextd.
572 */
573 void
moduleHasLoaded(const OSSymbol * moduleName)574 IOCatalogue::moduleHasLoaded(const OSSymbol * moduleName)
575 {
576 startMatching(moduleName);
577
578 (void) OSKext::setDeferredLoadSucceeded();
579 (void) OSKext::considerRebuildOfPrelinkedKernel();
580 }
581
582 void
moduleHasLoaded(const char * moduleName)583 IOCatalogue::moduleHasLoaded(const char * moduleName)
584 {
585 OSSharedPtr<const OSSymbol> name;
586
587 name = OSSymbol::withCString(moduleName);
588 moduleHasLoaded(name.get());
589 }
590
591 // xxx - return is really OSReturn/kern_return_t
592 IOReturn
unloadModule(OSString * moduleName) const593 IOCatalogue::unloadModule(OSString * moduleName) const
594 {
595 return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
596 }
597
598 IOReturn
terminateDrivers(OSDictionary * matching,io_name_t className)599 IOCatalogue::terminateDrivers(OSDictionary * matching, io_name_t className)
600 {
601 OSDictionary * dict;
602 OSSharedPtr<OSIterator> iter;
603 IOService * service;
604 IOReturn ret;
605
606 ret = kIOReturnSuccess;
607 dict = NULL;
608 iter = IORegistryIterator::iterateOver(gIOServicePlane,
609 kIORegistryIterateRecursively);
610 if (!iter) {
611 return kIOReturnNoMemory;
612 }
613
614 if (matching) {
615 OSKext::uniquePersonalityProperties( matching, false );
616 }
617
618 // terminate instances.
619 do {
620 iter->reset();
621 while ((service = (IOService *)iter->getNextObject())) {
622 if (className && !service->metaCast(className)) {
623 continue;
624 }
625 if (matching) {
626 /* Terminate only for personalities that match the matching dictionary.
627 * This comparison must be done with only the keys in the
628 * "matching" dict to enable general matching.
629 */
630 dict = service->getPropertyTable();
631 if (!dict) {
632 continue;
633 }
634 if (!dict->isEqualTo(matching, matching)) {
635 continue;
636 }
637 }
638
639 OSKext * kext;
640 OSSharedPtr<OSString> dextBundleID;
641 const char * bundleIDStr;
642 OSObject * prop;
643 bool okToTerminate;
644 bool isDext = service->hasUserServer();
645 for (okToTerminate = true;;) {
646 if (isDext) {
647 dextBundleID = OSDynamicPtrCast<OSString>(service->copyProperty(gIOModuleIdentifierKey.get()));
648 if (!dextBundleID) {
649 break;
650 }
651 bundleIDStr = dextBundleID->getCStringNoCopy();
652 } else {
653 kext = service->getMetaClass()->getKext();
654 if (!kext) {
655 break;
656 }
657 bundleIDStr = kext->getIdentifierCString();
658 prop = kext->getPropertyForHostArch(kOSBundleAllowUserTerminateKey);
659 if (prop) {
660 okToTerminate = (kOSBooleanTrue == prop);
661 break;
662 }
663 }
664 if (!bundleIDStr) {
665 break;
666 }
667 if (!strcmp(kOSKextKernelIdentifier, bundleIDStr)) {
668 okToTerminate = false;
669 break;
670 }
671 if (!strncmp("com.apple.", bundleIDStr, strlen("com.apple."))) {
672 okToTerminate = false;
673 break;
674 }
675 break;
676 }
677 if (!okToTerminate) {
678 #if DEVELOPMENT || DEBUG
679 okToTerminate = true;
680 #endif /* DEVELOPMENT || DEBUG */
681 IOLog("%sallowing kextunload terminate for bundleID %s\n",
682 okToTerminate ? "" : "dis", bundleIDStr ? bundleIDStr : "?");
683 if (!okToTerminate) {
684 ret = kIOReturnUnsupported;
685 break;
686 }
687 }
688 IOOptionBits terminateOptions = kIOServiceRequired | kIOServiceSynchronous;
689 if (isDext) {
690 terminateOptions |= kIOServiceTerminateNeedWillTerminate;
691 }
692 if (!service->terminate(terminateOptions)) {
693 ret = kIOReturnUnsupported;
694 break;
695 }
696 }
697 } while (!service && !iter->isValid());
698
699 return ret;
700 }
701
702 IOReturn
_removeDrivers(OSDictionary * matching)703 IOCatalogue::_removeDrivers(OSDictionary * matching)
704 {
705 IOReturn ret = kIOReturnSuccess;
706 OSSharedPtr<OSCollectionIterator> iter;
707 OSDictionary * dict;
708 OSArray * array;
709 const OSSymbol * key;
710 unsigned int idx;
711
712 // remove configs from catalog.
713
714 iter = OSCollectionIterator::withCollection(personalities.get());
715 if (!iter) {
716 return kIOReturnNoMemory;
717 }
718
719 while ((key = (const OSSymbol *) iter->getNextObject())) {
720 array = (OSArray *) personalities->getObject(key);
721 if (array) {
722 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
723 /* Remove from the catalogue's array any personalities
724 * that match the matching dictionary.
725 * This comparison must be done with only the keys in the
726 * "matching" dict to enable general matching.
727 */
728 if (dict->isEqualTo(matching, matching)) {
729 array->removeObject(idx);
730 idx--;
731 }
732 }
733 }
734 }
735
736 return ret;
737 }
738
739 IOReturn
terminateDrivers(OSDictionary * matching)740 IOCatalogue::terminateDrivers(OSDictionary * matching)
741 {
742 IOReturn ret;
743
744 if (!matching) {
745 return kIOReturnBadArgument;
746 }
747 ret = terminateDrivers(matching, NULL);
748 IORWLockWrite(lock);
749 if (kIOReturnSuccess == ret) {
750 ret = _removeDrivers(matching);
751 }
752 IORWLockUnlock(lock);
753
754 return ret;
755 }
756
757 IOReturn
terminateDriversForUserspaceReboot()758 IOCatalogue::terminateDriversForUserspaceReboot()
759 {
760 IOReturn ret = kIOReturnSuccess;
761
762 #if !NO_KEXTD
763 OSSharedPtr<OSIterator> iter;
764 IOService * service;
765 bool isDeferredMatch;
766 bool isDext;
767 IOOptionBits terminateOptions;
768
769 iter = IORegistryIterator::iterateOver(gIOServicePlane,
770 kIORegistryIterateRecursively);
771 if (!iter) {
772 return kIOReturnNoMemory;
773 }
774
775 do {
776 iter->reset();
777 while ((service = (IOService *)iter->getNextObject())) {
778 isDeferredMatch = service->propertyHasValue(gIOMatchDeferKey, kOSBooleanTrue);
779 isDext = service->hasUserServer();
780 if (isDeferredMatch || isDext) {
781 if (isDext) {
782 OSSharedPtr<OSString> name = OSDynamicPtrCast<OSString>(service->copyProperty(gIOUserServerNameKey));
783 const char *userServerName = NULL;
784 if (name) {
785 userServerName = name->getCStringNoCopy();
786 }
787 IOLog("terminating service %s-0x%llx [dext %s]\n", service->getName(), service->getRegistryEntryID(), userServerName ? userServerName : "(null)");
788 } else {
789 OSKext *kext = service->getMetaClass()->getKext();
790 const char *bundleID = NULL;
791 if (kext) {
792 bundleID = kext->getIdentifierCString();
793 }
794 IOLog("terminating service %s-0x%llx [kext %s]\n", service->getName(), service->getRegistryEntryID(), bundleID ? bundleID : "(null)");
795 }
796 terminateOptions = kIOServiceRequired | kIOServiceSynchronous;
797 if (isDext) {
798 terminateOptions |= kIOServiceTerminateNeedWillTerminate;
799 }
800 if (!service->terminate(terminateOptions)) {
801 IOLog("failed to terminate service %s-0x%llx\n", service->getName(), service->getRegistryEntryID());
802 ret = kIOReturnUnsupported;
803 break;
804 }
805 }
806 }
807 } while (!service && !iter->isValid());
808 #endif
809
810 return ret;
811 }
812
813 IOReturn
resetAfterUserspaceReboot(void)814 IOCatalogue::resetAfterUserspaceReboot(void)
815 {
816 OSSharedPtr<OSIterator> iter;
817 IOService * service;
818
819 iter = IORegistryIterator::iterateOver(gIOServicePlane,
820 kIORegistryIterateRecursively);
821 if (!iter) {
822 return kIOReturnNoMemory;
823 }
824
825 do {
826 iter->reset();
827 while ((service = (IOService *)iter->getNextObject())) {
828 service->resetRematchProperties();
829 }
830 } while (!service && !iter->isValid());
831
832 /* Remove all dext personalities */
833 removeDrivers(false, ^(OSDictionary *dict) {
834 return dict->getObject(gIOUserServerNameKey) != NULL;
835 });
836
837 return kIOReturnSuccess;
838 }
839
840 IOReturn
terminateDriversForModule(OSString * moduleName,bool unload)841 IOCatalogue::terminateDriversForModule(
842 OSString * moduleName,
843 bool unload)
844 {
845 IOReturn ret;
846 OSSharedPtr<OSDictionary> dict;
847 OSSharedPtr<OSKext> kext;
848 bool isLoaded = false;
849 bool isDext = false;
850
851 /* Check first if the kext currently has any linkage dependents;
852 * in such a case the unload would fail so let's not terminate any
853 * IOServices (since doing so typically results in a panic when there
854 * are loaded dependencies). Note that we aren't locking the kext here
855 * so it might lose or gain dependents by the time we call unloadModule();
856 * I think that's ok, our unload can fail if a kext comes in on top of
857 * this one even after we've torn down IOService objects. Conversely,
858 * if we fail the unload here and then lose a library, the autounload
859 * thread will get us in short order.
860 */
861 if (OSKext::isKextWithIdentifierLoaded(moduleName->getCStringNoCopy())) {
862 isLoaded = true;
863
864 if (!OSKext::canUnloadKextWithIdentifier(moduleName,
865 /* checkClasses */ false)) {
866 ret = kOSKextReturnInUse;
867 goto finish;
868 }
869 }
870 kext = OSKext::lookupKextWithIdentifier(moduleName->getCStringNoCopy());
871 if (kext) {
872 isDext = kext->isDriverKit();
873 }
874
875 dict = OSDictionary::withCapacity(1);
876 if (!dict) {
877 ret = kIOReturnNoMemory;
878 goto finish;
879 }
880
881 dict->setObject(gIOModuleIdentifierKey.get(), moduleName);
882
883 ret = terminateDrivers(dict.get(), NULL);
884
885 if (isDext) {
886 /* Force rematching after removing personalities. Dexts are never considered to be "loaded" (from OSKext),
887 * so we can't call unloadModule() to remove personalities and start rematching. */
888 removeDrivers(dict.get(), true);
889 } else {
890 /* No goto between IOLock calls!
891 */
892 IORWLockWrite(lock);
893 if (kIOReturnSuccess == ret) {
894 ret = _removeDrivers(dict.get());
895 }
896
897 // Unload the module itself.
898 if (unload && isLoaded && ret == kIOReturnSuccess) {
899 ret = unloadModule(moduleName);
900 }
901 IORWLockUnlock(lock);
902 }
903
904 finish:
905 return ret;
906 }
907
908 IOReturn
terminateDriversForModule(const char * moduleName,bool unload)909 IOCatalogue::terminateDriversForModule(
910 const char * moduleName,
911 bool unload)
912 {
913 OSSharedPtr<OSString> name;
914 IOReturn ret;
915
916 name = OSString::withCString(moduleName);
917 if (!name) {
918 return kIOReturnNoMemory;
919 }
920
921 ret = terminateDriversForModule(name.get(), unload);
922
923 return ret;
924 }
925
926 #if defined(__i386__) || defined(__x86_64__)
927 bool
startMatching(OSDictionary * matching)928 IOCatalogue::startMatching( OSDictionary * matching )
929 {
930 OSSharedPtr<OSOrderedSet> set;
931
932 if (!matching) {
933 return false;
934 }
935
936 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
937 (void *)(gIOProbeScoreKey.get()));
938 if (!set) {
939 return false;
940 }
941
942 IORWLockRead(lock);
943
944 personalities->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
945 OSArray * array;
946 OSDictionary * dict;
947 unsigned int idx;
948
949 array = (OSArray *) value;
950 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
951 /* This comparison must be done with only the keys in the
952 * "matching" dict to enable general matching.
953 */
954 if (dict->isEqualTo(matching, matching)) {
955 set->setObject(dict);
956 }
957 }
958 return false;
959 });
960
961 // Start device matching.
962 if (set->getCount() > 0) {
963 IOService::catalogNewDrivers(set.get());
964 generation++;
965 }
966
967 IORWLockUnlock(lock);
968
969 return true;
970 }
971 #endif /* defined(__i386__) || defined(__x86_64__) */
972
973 bool
startMatching(const OSSymbol * moduleName)974 IOCatalogue::startMatching( const OSSymbol * moduleName )
975 {
976 OSSharedPtr<OSOrderedSet> set;
977 OSSharedPtr<OSKext> kext;
978 OSSharedPtr<OSArray> servicesToTerminate;
979
980 if (!moduleName) {
981 return false;
982 }
983
984 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
985 (void *)(gIOProbeScoreKey.get()));
986 if (!set) {
987 return false;
988 }
989
990 IORWLockRead(lock);
991
992 kext = OSKext::lookupKextWithIdentifier(moduleName->getCStringNoCopy());
993 if (kext && kext->isDriverKit()) {
994 /* We're here because kernelmanagerd called IOCatalogueModuleLoaded after launching a dext.
995 * Determine what providers the dext would match against. If there's something already attached
996 * to the provider, terminate it.
997 *
998 * This is only safe to do for HID dexts.
999 */
1000 OSSharedPtr<OSArray> dextPersonalities = kext->copyPersonalitiesArray();
1001
1002 if (!dextPersonalities) {
1003 return false;
1004 }
1005
1006 servicesToTerminate = OSArray::withCapacity(1);
1007 if (!servicesToTerminate) {
1008 return false;
1009 }
1010
1011 dextPersonalities->iterateObjects(^bool (OSObject * obj) {
1012 OSDictionary * personality = OSDynamicCast(OSDictionary, obj);
1013 OSSharedPtr<OSIterator> iter;
1014 IOService * provider;
1015 OSSharedPtr<IOService> service;
1016 const OSSymbol * category;
1017
1018 if (personality) {
1019 category = OSDynamicCast(OSSymbol, personality->getObject(gIOMatchCategoryKey));
1020 if (!category) {
1021 category = gIODefaultMatchCategoryKey;
1022 }
1023 iter = IOService::getMatchingServices(personality);
1024
1025 while (iter && (provider = OSDynamicCast(IOService, iter->getNextObject()))) {
1026 if (provider->metaCast(gIOHIDInterfaceClassName.get()) != NULL) {
1027 service.reset(provider->copyClientWithCategory(category), OSNoRetain);
1028 if (service) {
1029 servicesToTerminate->setObject(service);
1030 }
1031 }
1032 }
1033 }
1034
1035 return false;
1036 });
1037 }
1038
1039 personalities->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
1040 OSArray * array;
1041 OSDictionary * dict;
1042 OSObject * moduleIdentifierKernel;
1043 OSObject * moduleIdentifier;
1044 unsigned int idx;
1045
1046 array = (OSArray *) value;
1047 for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) {
1048 moduleIdentifierKernel = dict->getObject(gIOModuleIdentifierKernelKey.get());
1049 moduleIdentifier = dict->getObject(gIOModuleIdentifierKey.get());
1050 if ((moduleIdentifierKernel && moduleName->isEqualTo(moduleIdentifierKernel)) ||
1051 (moduleIdentifier && moduleName->isEqualTo(moduleIdentifier))) {
1052 set->setObject(dict);
1053 }
1054 }
1055 return false;
1056 });
1057
1058 if (servicesToTerminate) {
1059 servicesToTerminate->iterateObjects(^bool (OSObject * obj) {
1060 IOService * service = OSDynamicCast(IOService, obj);
1061 if (service) {
1062 IOOptionBits terminateOptions = kIOServiceRequired;
1063 if (service->hasUserServer()) {
1064 terminateOptions |= kIOServiceTerminateNeedWillTerminate;
1065 }
1066 if (!service->terminate(terminateOptions)) {
1067 IOLog("%s: failed to terminate service %s-0x%qx with options %08llx for new dext %s\n", __FUNCTION__, service->getName(), service->getRegistryEntryID(), (long long)terminateOptions, moduleName->getCStringNoCopy());
1068 }
1069 }
1070 return false;
1071 });
1072 }
1073
1074 // Start device matching.
1075 if (set->getCount() > 0) {
1076 IOService::catalogNewDrivers(set.get());
1077 generation++;
1078 }
1079
1080 IORWLockUnlock(lock);
1081
1082 return true;
1083 }
1084
1085 void
reset(void)1086 IOCatalogue::reset(void)
1087 {
1088 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL,
1089 /* doMatching */ false);
1090 return;
1091 }
1092
1093 bool
resetAndAddDrivers(OSArray * drivers,bool doNubMatching)1094 IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching)
1095 {
1096 bool result = false;
1097 OSArray * newPersonalities = NULL;// do not release
1098 const OSSymbol * key;
1099 OSArray * array;
1100 OSDictionary * thisNewPersonality = NULL;// do not release
1101 OSDictionary * thisOldPersonality = NULL;// do not release
1102 OSSharedPtr<OSDictionary> myKexts;
1103 OSSharedPtr<OSCollectionIterator> iter;
1104 OSSharedPtr<OSOrderedSet> matchSet;
1105 signed int idx, newIdx;
1106
1107 if (drivers) {
1108 newPersonalities = OSDynamicCast(OSArray, drivers);
1109 if (!newPersonalities) {
1110 goto finish;
1111 }
1112 }
1113 matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering,
1114 (void *)(gIOProbeScoreKey.get()));
1115 if (!matchSet) {
1116 goto finish;
1117 }
1118 iter = OSCollectionIterator::withCollection(personalities.get());
1119 if (!iter) {
1120 goto finish;
1121 }
1122
1123 /* need copy of loaded kexts so we can check if for loaded modules without
1124 * taking the OSKext lock. There is a potential of deadlocking if we get
1125 * an OSKext via the normal path. See 14672140.
1126 */
1127 myKexts = OSKext::copyKexts();
1128
1129 result = true;
1130
1131 IOLog("Resetting IOCatalogue.\n");
1132
1133 /* No goto finish from here to unlock.
1134 */
1135 IORWLockWrite(lock);
1136
1137 while ((key = (const OSSymbol *) iter->getNextObject())) {
1138 array = (OSArray *) personalities->getObject(key);
1139 if (!array) {
1140 continue;
1141 }
1142
1143 for (idx = 0;
1144 (thisOldPersonality = (OSDictionary *) array->getObject(idx));
1145 idx++) {
1146 if (thisOldPersonality->getObject("KernelConfigTable")) {
1147 continue;
1148 }
1149 thisNewPersonality = NULL;
1150
1151 if (newPersonalities) {
1152 for (newIdx = 0;
1153 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
1154 newIdx++) {
1155 /* Unlike in other functions, this comparison must be exact!
1156 * The catalogue must be able to contain personalities that
1157 * are proper supersets of others.
1158 * Do not compare just the properties present in one driver
1159 * personality or the other.
1160 */
1161 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
1162 /* skip thisNewPersonality if it is not an OSDictionary */
1163 continue;
1164 }
1165 if (thisNewPersonality->isEqualTo(thisOldPersonality)) {
1166 break;
1167 }
1168 }
1169 }
1170 if (thisNewPersonality) {
1171 // dup, ignore
1172 newPersonalities->removeObject(newIdx);
1173 } else {
1174 // not in new set - remove
1175 // only remove dictionary if this module in not loaded - 9953845
1176 if (isModuleLoadedNoOSKextLock(myKexts.get(), thisOldPersonality) == false) {
1177 if (matchSet) {
1178 matchSet->setObject(thisOldPersonality);
1179 }
1180 array->removeObject(idx);
1181 idx--;
1182 }
1183 }
1184 } // for...
1185 } // while...
1186
1187 // add new
1188 if (newPersonalities) {
1189 for (newIdx = 0;
1190 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
1191 newIdx++) {
1192 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
1193 /* skip thisNewPersonality if it is not an OSDictionary */
1194 continue;
1195 }
1196
1197 OSKext::uniquePersonalityProperties(thisNewPersonality);
1198 addPersonality(thisNewPersonality);
1199 matchSet->setObject(thisNewPersonality);
1200 }
1201 }
1202
1203 /* Finally, start device matching on all new & removed personalities.
1204 */
1205 if (result && doNubMatching && (matchSet->getCount() > 0)) {
1206 IOService::catalogNewDrivers(matchSet.get());
1207 generation++;
1208 }
1209
1210 IORWLockUnlock(lock);
1211
1212 finish:
1213
1214 return result;
1215 }
1216
1217 bool
serialize(OSSerialize * s) const1218 IOCatalogue::serialize(OSSerialize * s) const
1219 {
1220 if (!s) {
1221 return false;
1222 }
1223
1224 return super::serialize(s);
1225 }
1226
1227 bool
serializeData(IOOptionBits kind,OSSerialize * s) const1228 IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
1229 {
1230 kern_return_t kr = kIOReturnSuccess;
1231
1232 switch (kind) {
1233 case kIOCatalogGetContents:
1234 kr = KERN_NOT_SUPPORTED;
1235 break;
1236
1237 case kIOCatalogGetModuleDemandList:
1238 kr = KERN_NOT_SUPPORTED;
1239 break;
1240
1241 case kIOCatalogGetCacheMissList:
1242 kr = KERN_NOT_SUPPORTED;
1243 break;
1244
1245 case kIOCatalogGetROMMkextList:
1246 kr = KERN_NOT_SUPPORTED;
1247 break;
1248
1249 default:
1250 kr = kIOReturnBadArgument;
1251 break;
1252 }
1253
1254 return kr;
1255 }
1256
1257 /* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
1258 * without taking the OSKext lock. We use this to avoid the problem
1259 * where taking the IOCatalog lock then the OSKext lock will dealock when
1260 * a kext load or unload is happening at the same time as IOCatalog changing.
1261 *
1262 * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
1263 * key set to the kext bundle ID and value set to an OSKext object
1264 * theModuleDict - is an IOKit personality dictionary for a given module (kext)
1265 */
1266 static bool
isModuleLoadedNoOSKextLock(OSDictionary * theKexts,OSDictionary * theModuleDict)1267 isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
1268 OSDictionary *theModuleDict)
1269 {
1270 bool myResult = false;
1271 const OSString * myBundleID = NULL;// do not release
1272 OSKext * myKext = NULL; // do not release
1273
1274 if (theKexts == NULL || theModuleDict == NULL) {
1275 return myResult;
1276 }
1277
1278 // gIOModuleIdentifierKey is "CFBundleIdentifier"
1279 myBundleID = OSDynamicCast(OSString,
1280 theModuleDict->getObject(gIOModuleIdentifierKey.get()));
1281 if (myBundleID == NULL) {
1282 return myResult;
1283 }
1284
1285 myKext = OSDynamicCast(OSKext, theKexts->getObject(myBundleID->getCStringNoCopy()));
1286 if (myKext) {
1287 myResult = myKext->isLoaded();
1288 }
1289
1290 return myResult;
1291 }
1292
1293
1294 #if PRAGMA_MARK
1295 #pragma mark Obsolete Kext Loading Stuff
1296 #endif
1297 /*********************************************************************
1298 **********************************************************************
1299 *** BINARY COMPATIBILITY SECTION ***
1300 **********************************************************************
1301 **********************************************************************
1302 * These functions are no longer used are necessary for C++ binary
1303 * compatibility on i386.
1304 **********************************************************************/
1305