xref: /xnu-8020.140.41/iokit/Kernel/IOCatalogue.cpp (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
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