1/* 2 * Copyright (c) 2012 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_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. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#include <asl.h> 24#include <IOKit/kext/OSKext.h> 25#include <IOKit/kext/OSKextPrivate.h> 26#include <IOKit/IOKitLib.h> 27#include <Security/Security.h> 28 29#include "security.h" 30#include "kext_tools_util.h" 31 32/******************************************************************************* 33 * Helper functions 34 *******************************************************************************/ 35static OSStatus checkRootCertificateIsApple(OSKextRef aKext); 36static CFStringRef copyCDHash(SecStaticCodeRef code); 37static CFStringRef copyIssuerCN(SecCertificateRef certificate); 38static void copySigningInfo(CFURLRef kextURL, 39 CFStringRef* cdhash, 40 CFStringRef* teamId, 41 CFStringRef* subjectCN, 42 CFStringRef* issuerCN); 43static CFArrayRef copySubjectCNArray(CFURLRef kextURL); 44static CFStringRef copyTeamID(SecCertificateRef certificate); 45static CFStringRef createArchitectureList(OSKextRef aKext, CFBooleanRef *isFat); 46static void createHashForMT(CFURLRef kextURL, char ** signatureBuffer); 47static void filterKextLoadForMT(OSKextRef aKext, CFMutableArrayRef *kextList); 48 49/******************************************************************************* 50 * messageTraceExcludedKext() - log MessageTracer message for kexts in 51 * exclude list. 52 * <rdar://problem/12994418> MessageTrace when we block the load of something 53 * on the kext exclude list 54 *******************************************************************************/ 55 56void messageTraceExcludedKext(OSKextRef theKext) 57{ 58 CFStringRef versionString; 59 CFStringRef bundleIDString; 60 CFURLRef kextURL = NULL; // must release 61 CFStringRef filename = NULL; // must release 62 aslmsg amsg = NULL; // must free 63 char *versionCString = NULL; // must free 64 char *bundleIDCString = NULL; // must free 65 char *filenameCString = NULL; // must free 66 67 kextURL = CFURLCopyAbsoluteURL(OSKextGetURL(theKext)); 68 if (!kextURL) { 69 OSKextLogMemError(); 70 goto finish; 71 } 72 versionString = OSKextGetValueForInfoDictionaryKey(theKext, 73 kCFBundleVersionKey); 74 if (versionString) { 75 versionCString = createUTF8CStringForCFString(versionString); 76 } 77 bundleIDString = OSKextGetValueForInfoDictionaryKey(theKext, 78 kCFBundleIdentifierKey); 79 if (bundleIDString) { 80 bundleIDCString = createUTF8CStringForCFString(bundleIDString); 81 } 82 83 filename = CFURLCopyLastPathComponent(kextURL); 84 if (filename) { 85 filenameCString = createUTF8CStringForCFString(filename); 86 } 87 SAFE_RELEASE(filename); 88 89 /* log the message tracer data 90 */ 91 amsg = asl_new(ASL_TYPE_MSG); 92 if (!amsg) { 93 OSKextLogMemError(); 94 goto finish; 95 } 96 97 asl_set(amsg, kMessageTracerDomainKey, kMTKextBlockedDomain); 98 asl_set(amsg, kMessageTracerBundleIDKey, 99 bundleIDCString ? bundleIDCString : ""); 100 asl_set(amsg, kMessageTracerVersionKey, 101 versionCString ? versionCString : ""); 102 asl_set(amsg, kMessageTracerKextNameKey, 103 filenameCString ? filenameCString : ""); 104 105 asl_log(NULL, amsg, ASL_LEVEL_NOTICE, ""); 106 107finish: 108 SAFE_FREE(versionCString); 109 SAFE_FREE(bundleIDCString); 110 SAFE_FREE(filenameCString); 111 112 SAFE_RELEASE(kextURL); 113 114 if (amsg) { 115 asl_free(amsg); 116 } 117 return; 118} 119 120/******************************************************************************* 121 * checkRootCertificateIsApple() - check if the root certificate of the kext 122 * is issued by Apple 123 * <rdar://problem/12435992> 124 *******************************************************************************/ 125static OSStatus checkRootCertificateIsApple(OSKextRef aKext) 126{ 127 OSStatus result = -1; 128 CFURLRef kextURL = NULL; // must release 129 SecStaticCodeRef staticCodeRef = NULL; // must release 130 SecRequirementRef requirementRef = NULL; // must release 131 CFStringRef myCFString; 132 CFStringRef requirementsString; 133 134 if (aKext == NULL) { 135 return result; 136 } 137 138 kextURL = CFURLCopyAbsoluteURL(OSKextGetURL(aKext)); 139 if (!kextURL) { 140 OSKextLogMemError(); 141 goto finish; 142 } 143 144 if (SecStaticCodeCreateWithPath(kextURL, 145 kSecCSDefaultFlags, 146 &staticCodeRef) != errSecSuccess || 147 (staticCodeRef == NULL)) { 148 OSKextLogMemError(); 149 goto finish; 150 } 151 152 /* set up correct requirement string */ 153 myCFString = OSKextGetIdentifier(aKext); 154 if (CFStringHasPrefix(myCFString, __kOSKextApplePrefix)) { 155 requirementsString = CFSTR("anchor apple"); 156 } 157 else { 158 requirementsString = CFSTR("anchor apple generic"); 159 } 160 161 if (SecRequirementCreateWithString(requirementsString, 162 kSecCSDefaultFlags, 163 &requirementRef) != errSecSuccess || 164 (requirementRef == NULL)) { 165 OSKextLogMemError(); 166 goto finish; 167 } 168 169 // errSecCSUnsigned == -67062 170 result = SecStaticCodeCheckValidity(staticCodeRef, 171 kSecCSDefaultFlags, 172 requirementRef); 173 if (result != 0) { 174 OSKextLogCFString(NULL, 175 kOSKextLogErrorLevel | kOSKextLogLoadFlag, 176 CFSTR("Invalid signature %ld for kext %@"), 177 (long)result, aKext); 178 } 179 180finish: 181 SAFE_RELEASE(kextURL); 182 SAFE_RELEASE(staticCodeRef); 183 SAFE_RELEASE(requirementRef); 184 185 return result; 186} 187 188/******************************************************************************* 189 * createHashForMT() - create a hash signature for the kext 190 * <rdar://problem/12435992> 191 *******************************************************************************/ 192 193static void createHashForMT(CFURLRef kextURL, char ** signatureBuffer) 194{ 195 CFMutableDictionaryRef signdict = NULL; // must release 196 SecCodeSignerRef signerRef = NULL; // must release 197 SecStaticCodeRef staticCodeRef = NULL; // must release 198 CFDataRef signature = NULL; // must release 199 CFDictionaryRef signingDict = NULL; // must release 200 CFDataRef cdhash = NULL; // must release 201 CFMutableDictionaryRef resourceRules = NULL; // must release 202 CFMutableDictionaryRef rules = NULL; // must release 203 CFMutableDictionaryRef omitPlugins = NULL; // must release 204 char * tempBufPtr = NULL; // do not free 205 206 if (!kextURL || !signatureBuffer) { 207 return; 208 } 209 210 /* Ad-hoc sign the code temporarily so we can get its hash */ 211 if (SecStaticCodeCreateWithPath(kextURL, 212 kSecCSDefaultFlags, 213 &staticCodeRef) != 0 || 214 (staticCodeRef == NULL)) { 215 OSKextLogMemError(); 216 goto finish; 217 } 218 219 signature = CFDataCreateMutable(NULL, 0); 220 if (signature == NULL) { 221 OSKextLogMemError(); 222 goto finish; 223 } 224 225 signdict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 226 &kCFTypeDictionaryKeyCallBacks, 227 &kCFTypeDictionaryValueCallBacks); 228 if (signdict == NULL) { 229 OSKextLogMemError(); 230 goto finish; 231 } 232 233 CFDictionarySetValue(signdict, kSecCodeSignerIdentity, kCFNull); 234 CFDictionarySetValue(signdict, kSecCodeSignerDetached, signature); 235 236 resourceRules = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 237 &kCFTypeDictionaryKeyCallBacks, 238 &kCFTypeDictionaryValueCallBacks); 239 if (resourceRules == NULL) { 240 OSKextLogMemError(); 241 goto finish; 242 } 243 244 rules = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 245 &kCFTypeDictionaryKeyCallBacks, 246 &kCFTypeDictionaryValueCallBacks); 247 if (rules == NULL) { 248 OSKextLogMemError(); 249 goto finish; 250 } 251 252 omitPlugins = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 253 &kCFTypeDictionaryKeyCallBacks, 254 &kCFTypeDictionaryValueCallBacks); 255 if (omitPlugins == NULL) { 256 OSKextLogMemError(); 257 goto finish; 258 } 259 260 /* exclude PlugIns directory 261 */ 262 CFNumberRef myNumValue; 263 int myNum = 100; 264 myNumValue = CFNumberCreate(kCFAllocatorDefault, 265 kCFNumberIntType, &myNum); 266 if (myNumValue == NULL) { 267 OSKextLogMemError(); 268 goto finish; 269 } 270 271 CFDictionarySetValue(omitPlugins, CFSTR("omit"), kCFBooleanTrue); 272 CFDictionarySetValue(omitPlugins, CFSTR("weight"), myNumValue); 273 CFRelease( myNumValue ); 274 275 CFDictionarySetValue(rules, CFSTR("^.*"), kCFBooleanTrue); 276 CFDictionarySetValue(rules, CFSTR("^PlugIns/"), omitPlugins); 277 CFDictionarySetValue(resourceRules, CFSTR("rules"), rules); 278 CFDictionarySetValue(signdict, kSecCodeSignerResourceRules, resourceRules); 279 280 if (SecCodeSignerCreate(signdict, kSecCSDefaultFlags, &signerRef) != 0) { 281 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogGeneralFlag, 282 "%s - SecCodeSignerCreate failed", __func__); 283 goto finish; 284 } 285 if (SecCodeSignerAddSignature(signerRef, staticCodeRef, kSecCSDefaultFlags) != 0) { 286 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogGeneralFlag, 287 "%s - SecCodeSignerAddSignature failed", __func__); 288 goto finish; 289 } 290 if (SecCodeSetDetachedSignature(staticCodeRef, signature, kSecCSDefaultFlags) != 0) { 291 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogGeneralFlag, 292 "%s - SecCodeSetDetachedSignature failed", __func__); 293 goto finish; 294 } 295 296 /* get the hash info 297 */ 298 if (SecCodeCopySigningInformation(staticCodeRef, kSecCSDefaultFlags, &signingDict) != 0) { 299 OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogGeneralFlag, 300 "%s - SecCodeCopySigningInformation failed", __func__); 301 goto finish; 302 } 303 304 cdhash = CFRetain(CFDictionaryGetValue(signingDict, kSecCodeInfoUnique)); 305 if (cdhash) { 306 const UInt8 * hashDataPtr = NULL; // don't free 307 CFIndex hashDataLen = 0; 308 309 hashDataPtr = CFDataGetBytePtr(cdhash); 310 hashDataLen = CFDataGetLength(cdhash); 311 tempBufPtr = (char *) malloc((hashDataLen + 1) * 2); 312 if (tempBufPtr == NULL) { 313 OSKextLogMemError(); 314 goto finish; 315 } 316#if 0 317 OSKextLogCFString(/* kext */ NULL, 318 kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 319 CFSTR("%s - cdhash %@"), 320 __func__, 321 cdhash); 322#endif 323 324 bzero(tempBufPtr, ((hashDataLen + 1) * 2)); 325 for (int i = 0; i < hashDataLen; i++) { 326 sprintf(tempBufPtr + (i * 2), "%02.2x", *(hashDataPtr + i)); 327 } 328 } 329 330finish: 331 SAFE_RELEASE(signdict); 332 SAFE_RELEASE(signerRef); 333 SAFE_RELEASE(staticCodeRef); 334 SAFE_RELEASE(signature); 335 SAFE_RELEASE(signingDict); 336 SAFE_RELEASE(cdhash); 337 SAFE_RELEASE(resourceRules); 338 SAFE_RELEASE(rules); 339 SAFE_RELEASE(omitPlugins); 340 341 *signatureBuffer = tempBufPtr; 342} 343 344/******************************************************************************* 345 * createArchitectureList() - create the list of architectures for the kext 346 * <rdar://13529984> 347 * Note: the caller must release the created CFStringRef 348 *******************************************************************************/ 349static CFStringRef createArchitectureList(OSKextRef aKext, CFBooleanRef *isFat) 350{ 351 if (aKext == NULL || isFat == NULL) { 352 return NULL; 353 } 354 355 *isFat = kCFBooleanFalse; 356 357 const NXArchInfo ** archList = NULL; // must free 358 CFMutableArrayRef archNamesList = NULL; // must release 359 CFStringRef archNames = NULL; // do not release 360 const char * archNameCString = NULL; // do not free 361 int index = 0; 362 363 archList = OSKextCopyArchitectures(aKext); 364 if (!archList) { 365 goto finish; 366 } 367 368 archNamesList = CFArrayCreateMutable(kCFAllocatorDefault, 369 0, 370 &kCFTypeArrayCallBacks); 371 if (!archNamesList) { 372 goto finish; 373 } 374 375 for (index=0; archList[index]; index++) { 376 archNameCString = archList[index]->name; 377 if (archNameCString) { 378 CFStringRef archName = NULL; 379 archName = CFStringCreateWithCString(kCFAllocatorDefault, 380 archNameCString, 381 kCFStringEncodingUTF8); 382 if (archName) { 383 CFArrayAppendValue(archNamesList, archName); 384 SAFE_RELEASE_NULL(archName); 385 } 386 } 387 } 388 389 if (index>1) { 390 *isFat = kCFBooleanTrue; 391 } 392 archNames = CFStringCreateByCombiningStrings(kCFAllocatorDefault, 393 archNamesList, 394 CFSTR(" ")); 395 if (!archNames) { 396 goto finish; 397 } 398 399finish: 400 SAFE_RELEASE(archNamesList); 401 SAFE_FREE(archList); 402 403 return archNames; 404} 405 406/******************************************************************************* 407 * copyTeamID() - copy the team id field from the given certificate 408 * <rdar://13646260> 409 * Note: the caller must release the created CFStringRef 410 *******************************************************************************/ 411static CFStringRef copyTeamID(SecCertificateRef certificate) 412{ 413 if (!certificate || 414 CFGetTypeID(certificate) !=SecCertificateGetTypeID()) { 415 return NULL; 416 } 417 418 CFDictionaryRef subjectDict = NULL; // do not release 419 CFArrayRef subjectArray = NULL; // do not release 420 CFDictionaryRef subjectInfo = NULL; // do not release 421 CFStringRef teamID = NULL; // do not release 422 CFErrorRef error = NULL; // do not release 423 424 CFMutableArrayRef certificateKeys = NULL; // must release 425 CFDictionaryRef certificateDict = NULL; // must release 426 427 certificateKeys = CFArrayCreateMutable(kCFAllocatorDefault, 428 1, 429 &kCFTypeArrayCallBacks); 430 if (!certificateKeys) { 431 goto finish; 432 } 433 434 CFArrayAppendValue(certificateKeys, kSecOIDX509V1SubjectName); 435 436 certificateDict = SecCertificateCopyValues(certificate, 437 certificateKeys, 438 &error); 439 if (error != errSecSuccess || 440 !certificateDict || 441 CFGetTypeID(certificateDict) != CFDictionaryGetTypeID()) { 442 goto finish; 443 } 444 445 subjectDict = (CFDictionaryRef) CFDictionaryGetValue(certificateDict, 446 kSecOIDX509V1SubjectName); 447 if (!subjectDict || 448 CFGetTypeID(subjectDict) != CFDictionaryGetTypeID()) { 449 goto finish; 450 } 451 452 subjectArray = (CFArrayRef) CFDictionaryGetValue(subjectDict, 453 kSecPropertyKeyValue); 454 if (!subjectArray || 455 CFGetTypeID(subjectArray) != CFArrayGetTypeID()) { 456 goto finish; 457 } 458 459 // Try to look for UserID field ("0.9.2342.19200300.100.1.1") 460 for (int index=0; index<CFArrayGetCount(subjectArray); index++) { 461 subjectInfo = (CFDictionaryRef) CFArrayGetValueAtIndex(subjectArray, 462 index); 463 if (!subjectInfo || 464 CFGetTypeID(subjectInfo) != CFDictionaryGetTypeID()) { 465 continue; 466 } 467 468 CFStringRef label = NULL; // do not release 469 label = CFDictionaryGetValue(subjectInfo, 470 kSecPropertyKeyLabel); 471 if (kCFCompareEqualTo == CFStringCompare(label, 472 CFSTR("0.9.2342.19200300.100.1.1"), 473 0)) { 474 teamID = CFDictionaryGetValue(subjectInfo, 475 kSecPropertyKeyValue); 476 if (teamID && 477 CFGetTypeID(teamID) == CFStringGetTypeID()) { 478 CFRetain(teamID); 479 goto finish; 480 } 481 else { 482 teamID = NULL; 483 } 484 } 485 } 486 487 // In case of failure, look for OU field ("2.5.4.11") 488 if (!teamID) { 489 for (int index=0; index<CFArrayGetCount(subjectArray); index++) { 490 subjectInfo = (CFDictionaryRef) CFArrayGetValueAtIndex(subjectArray, 491 index); 492 if (!subjectInfo || 493 CFGetTypeID(subjectInfo) != CFDictionaryGetTypeID()) { 494 continue; 495 } 496 497 CFStringRef label = NULL; // do not release 498 label = CFDictionaryGetValue(subjectInfo, 499 kSecPropertyKeyLabel); 500 if (kCFCompareEqualTo == CFStringCompare(label, 501 CFSTR("2.5.4.11"), 502 0)) { 503 teamID = CFDictionaryGetValue(subjectInfo, 504 kSecPropertyKeyValue); 505 if (teamID && 506 CFGetTypeID(teamID) == CFStringGetTypeID()) { 507 CFRetain(teamID); 508 goto finish; 509 } 510 else { 511 teamID = NULL; 512 } 513 } 514 } 515 } 516 517finish: 518 if (!teamID && subjectArray) { 519 CFShow(subjectArray); 520 } 521 SAFE_RELEASE(certificateKeys); 522 SAFE_RELEASE(certificateDict); 523 return teamID; 524} 525 526/******************************************************************************* 527 * copyIssuerCN() - copy the issuer CN field from the given certificate 528 * <rdar://13646260> 529 * Note: the caller must release the created CFStringRef 530 *******************************************************************************/ 531static CFStringRef copyIssuerCN(SecCertificateRef certificate) 532{ 533 if (!certificate || 534 CFGetTypeID(certificate) !=SecCertificateGetTypeID()) { 535 return NULL; 536 } 537 538 CFStringRef issuerCN = NULL; // do not release 539 CFDictionaryRef issuerDict = NULL; // do not release 540 CFArrayRef issuerArray = NULL; // do not release 541 CFDictionaryRef issuerInfo = NULL; // do not release 542 CFErrorRef error = NULL; // do not release 543 544 CFMutableArrayRef certificateKeys = NULL; // must release 545 CFDictionaryRef certificateDict = NULL; // must release 546 547 certificateKeys = CFArrayCreateMutable(kCFAllocatorDefault, 548 1, 549 &kCFTypeArrayCallBacks); 550 if (!certificateKeys) { 551 goto finish; 552 } 553 554 CFArrayAppendValue(certificateKeys, kSecOIDX509V1IssuerName); 555 556 certificateDict = SecCertificateCopyValues(certificate, 557 certificateKeys, 558 &error); 559 560 if (error != errSecSuccess || 561 !certificateDict || 562 CFGetTypeID(certificateDict) != CFDictionaryGetTypeID()) { 563 goto finish; 564 } 565 566 issuerDict = (CFDictionaryRef) CFDictionaryGetValue(certificateDict, 567 kSecOIDX509V1IssuerName); 568 if (!issuerDict || 569 CFGetTypeID(issuerDict) != CFDictionaryGetTypeID()) { 570 goto finish; 571 } 572 573 issuerArray = (CFArrayRef) CFDictionaryGetValue(issuerDict, 574 kSecPropertyKeyValue); 575 if (!issuerArray || 576 CFGetTypeID(issuerArray) != CFArrayGetTypeID()) { 577 goto finish; 578 } 579 580 for (int index=0; index<CFArrayGetCount(issuerArray); index++) { 581 issuerInfo = (CFDictionaryRef) CFArrayGetValueAtIndex(issuerArray, 582 index); 583 if (!issuerInfo || 584 CFGetTypeID(issuerInfo) != CFDictionaryGetTypeID()) { 585 continue; 586 } 587 588 CFStringRef label = NULL; // do not release 589 label = CFDictionaryGetValue(issuerInfo, 590 kSecPropertyKeyLabel); 591 if (kCFCompareEqualTo == CFStringCompare(label, 592 CFSTR("2.5.4.3"), 593 0)) { 594 issuerCN = CFDictionaryGetValue(issuerInfo, 595 kSecPropertyKeyValue); 596 if (issuerCN && 597 CFGetTypeID(issuerCN) == CFStringGetTypeID()) { 598 CFRetain(issuerCN); 599 goto finish; 600 } 601 else { 602 issuerCN = NULL; 603 } 604 } 605 } 606 607finish: 608 SAFE_RELEASE(certificateDict); 609 SAFE_RELEASE(certificateKeys); 610 return issuerCN; 611} 612 613/******************************************************************************* 614 * copyCDHash() - copy the SHA-1 hash of the code 615 * <rdar://13646260> 616 * Note: the caller must release the created CFStringRef 617 *******************************************************************************/ 618static CFStringRef copyCDHash(SecStaticCodeRef code) 619{ 620 CFDictionaryRef signingInfo = NULL; // must release 621 char * tempBufPtr = NULL; // free 622 const UInt8 * hashDataPtr = NULL; // do not free 623 CFDataRef cdhash = NULL; // do not release 624 CFStringRef hash = NULL; // do not release 625 CFIndex hashDataLen = 0; 626 627 SecCodeCopySigningInformation(code, 628 kSecCSDefaultFlags, 629 &signingInfo); 630 if (!signingInfo) { 631 goto finish; 632 } 633 634 cdhash = CFDictionaryGetValue(signingInfo, kSecCodeInfoUnique); 635 if (!cdhash || 636 CFGetTypeID(cdhash) != CFDataGetTypeID()) { 637 goto finish; 638 } 639 640 hashDataPtr = CFDataGetBytePtr(cdhash); 641 hashDataLen = CFDataGetLength(cdhash); 642 tempBufPtr = (char *) malloc((hashDataLen + 1) * 2); 643 if (tempBufPtr == NULL) { 644 OSKextLogMemError(); 645 goto finish; 646 } 647 648 bzero(tempBufPtr, ((hashDataLen + 1) * 2)); 649 for (int i = 0; i < hashDataLen; i++) { 650 sprintf(tempBufPtr + (i * 2), "%02.2x", *(hashDataPtr + i)); 651 } 652 653 if (tempBufPtr) { 654 hash = CFStringCreateWithCString(kCFAllocatorDefault, 655 tempBufPtr, 656 kCFStringEncodingUTF8); 657 } 658 659finish: 660 SAFE_FREE(tempBufPtr); 661 SAFE_RELEASE(signingInfo); 662 return hash; 663} 664 665/******************************************************************************* 666 * copySigningInfo() - copy a set of signing information for the given kext 667 * cdhash: the SHA-1 hash 668 * teamid: the team id of the leaf certificate 669 * subjectCN: the subject common name of the leaf certificate 670 * issuerCN: the issuer common name of the leaf certificate 671 * <rdar://13646260> 672 * Note: the caller must release the created CFStringRefs 673 *******************************************************************************/ 674static void copySigningInfo(CFURLRef kextURL, 675 CFStringRef* cdhash, 676 CFStringRef* teamId, 677 CFStringRef* subjectCN, 678 CFStringRef* issuerCN) 679{ 680 if (!kextURL) { 681 return; 682 } 683 684 SecStaticCodeRef code = NULL; // must release 685 CFDictionaryRef information = NULL; // must release 686 687 SecCertificateRef issuerCertificate = NULL; // do not release 688 CFArrayRef certificateChain = NULL; // do not release 689 OSStatus status; 690 CFIndex count; 691 692 if (SecStaticCodeCreateWithPath(kextURL, 693 kSecCSDefaultFlags, 694 &code) != 0 695 || (code == NULL)) { 696 OSKextLogMemError(); 697 goto finish; 698 } 699 700 if (cdhash) { 701 *cdhash = copyCDHash(code); 702 } 703 704 status = SecCodeCopySigningInformation(code, 705 kSecCSSigningInformation, 706 &information); 707 if (status != noErr) { 708 goto finish; 709 } 710 711 // a CFArrayRef array of SecCertificateRef objects 712 certificateChain = (CFArrayRef) CFDictionaryGetValue(information, kSecCodeInfoCertificates); 713 if (!certificateChain || 714 CFGetTypeID(certificateChain) != CFArrayGetTypeID()) { 715 goto finish; 716 } 717 718 count = CFArrayGetCount(certificateChain); 719 if (count < 1) { 720 goto finish; 721 } 722 723 issuerCertificate = (SecCertificateRef) CFArrayGetValueAtIndex(certificateChain, 0); 724 if (!issuerCertificate) { 725 goto finish; 726 } 727 728 if (subjectCN) { 729 SecCertificateCopyCommonName(issuerCertificate, subjectCN); 730 } 731 732 if (teamId) { 733 *teamId = copyTeamID(issuerCertificate); 734 } 735 736 if (issuerCN) { 737 *issuerCN = copyIssuerCN(issuerCertificate); 738 } 739 740finish: 741 SAFE_RELEASE(code); 742 SAFE_RELEASE(information); 743 744 return; 745} 746 747/******************************************************************************* 748 * copySubjectCNArray() - copy the subject CN from every certificate in the kext's 749 * certificate chain. 750 * <rdar://13646260> 751 * Note: the caller must release the created CFArrayRef 752 *******************************************************************************/ 753static CFArrayRef copySubjectCNArray(CFURLRef kextURL) 754{ 755 if (!kextURL) { 756 return NULL; 757 } 758 759 CFMutableArrayRef subjectCNArray = NULL; // do not release 760 CFArrayRef certificateChain = NULL; // do not release 761 SecCertificateRef certificate = NULL; // do not release 762 763 SecStaticCodeRef code = NULL; // must release 764 CFDictionaryRef information = NULL; // must release 765 766 OSStatus status; 767 CFIndex count; 768 769 subjectCNArray = CFArrayCreateMutable(kCFAllocatorDefault, 770 0, 771 &kCFTypeArrayCallBacks); 772 if (!subjectCNArray) { 773 goto finish; 774 } 775 776 if (SecStaticCodeCreateWithPath(kextURL, 777 kSecCSDefaultFlags, 778 &code) != 0 779 || (code == NULL)) { 780 OSKextLogMemError(); 781 goto finish; 782 } 783 784 status = SecCodeCopySigningInformation(code, 785 kSecCSSigningInformation, 786 &information); 787 if (status != noErr) { 788 goto finish; 789 } 790 791 certificateChain = (CFArrayRef) CFDictionaryGetValue(information, kSecCodeInfoCertificates); 792 if (!certificateChain || 793 CFGetTypeID(certificateChain) != CFArrayGetTypeID()) { 794 goto finish; 795 } 796 797 count = CFArrayGetCount(certificateChain); 798 if (count < 1) { 799 goto finish; 800 } 801 802 for (CFIndex i=0; i<count; i++) { 803 certificate = (SecCertificateRef) CFArrayGetValueAtIndex(certificateChain, i); 804 CFStringRef subjectCN = NULL; // must release 805 SecCertificateCopyCommonName(certificate, &subjectCN); 806 if (subjectCN) { 807 CFArrayAppendValue(subjectCNArray, subjectCN); 808 SAFE_RELEASE(subjectCN); 809 } 810 } 811 812finish: 813 SAFE_RELEASE(code); 814 SAFE_RELEASE(information); 815 816 return subjectCNArray; 817} 818 819/******************************************************************************* 820 * filterKextLoadForMT() - check that the kext is of interest, and place kext 821 * information in the kext list 822 * <rdar://problem/12435992> 823 *******************************************************************************/ 824 825static void filterKextLoadForMT(OSKextRef aKext, CFMutableArrayRef *kextList) 826{ 827 if (aKext == NULL || kextList == NULL) 828 return; 829 830 CFStringRef versionString; // do not release 831 CFStringRef bundleIDString; // do not release 832 CFStringRef kextSigningCategory = NULL; // do not release 833 CFBooleanRef isFat = kCFBooleanFalse; // do not release 834 CFBooleanRef isSigned = kCFBooleanFalse; // do not release 835 836 CFURLRef kextURL = NULL; // must release 837 CFStringRef kextPath = NULL; // must release 838 CFStringRef filename = NULL; // must release 839 CFStringRef hashString = NULL; // must release 840 CFStringRef archString = NULL; // must release 841 CFStringRef teamId = NULL; // must release 842 CFStringRef subjectCN = NULL; // must release 843 CFStringRef issuerCN = NULL; // must release 844 845 SecStaticCodeRef code = NULL; // must release 846 CFDictionaryRef information = NULL; // must release 847 CFMutableDictionaryRef kextDict = NULL; // must release 848 849 char * hashCString = NULL; // must free 850 851 OSStatus status = noErr; 852 853 /* do not message trace this if boot-args has debug set */ 854 if (isDebugSetInBootargs()) { 855 return; 856 } 857 858 kextURL = CFURLCopyAbsoluteURL(OSKextGetURL(aKext)); 859 if (!kextURL) { 860 OSKextLogMemError(); 861 goto finish; 862 } 863 kextPath = CFURLCopyFileSystemPath(kextURL, kCFURLPOSIXPathStyle); 864 if (!kextPath) { 865 OSKextLogMemError(); 866 goto finish; 867 } 868 869 versionString = OSKextGetValueForInfoDictionaryKey(aKext, 870 kCFBundleVersionKey); 871 bundleIDString = OSKextGetValueForInfoDictionaryKey(aKext, 872 kCFBundleIdentifierKey); 873 filename = CFURLCopyLastPathComponent(kextURL); 874 875 archString = createArchitectureList(aKext, &isFat); 876 877 if (SecStaticCodeCreateWithPath(kextURL, 878 kSecCSDefaultFlags, 879 &code) != 0 880 || (code == NULL)) { 881 OSKextLogMemError(); 882 goto finish; 883 } 884 status = SecCodeCopySigningInformation(code, 885 kSecCSSigningInformation, 886 &information); 887 if (status != noErr) { 888 goto finish; 889 } 890 891 isSigned = CFDictionaryContainsKey(information, kSecCodeInfoIdentifier); 892 if (!isSigned) { 893 /* The kext is unsigned, so there is little information we can retrieve. 894 * A hash of the kext is generated for data collection. */ 895 kextSigningCategory = CFSTR(kUnsignedKext); 896 897 createHashForMT(kextURL, &hashCString); 898 if (hashCString) { 899 hashString = CFStringCreateWithCString(kCFAllocatorDefault, 900 hashCString, 901 kCFStringEncodingUTF8); 902 } 903 } 904 else { 905 CFStringRef myCFString = NULL; // do not release 906 myCFString = OSKextGetIdentifier(aKext); 907 status = checkKextSignature(aKext, true); 908 if (CFStringHasPrefix(myCFString, __kOSKextApplePrefix)) { 909 if (status == noErr) { 910 /* This is a signed Apple kext, with an Apple root certificate. 911 * There is no need to retrieve additional signing information */ 912 kextSigningCategory = CFSTR(kAppleKextWithAppleRoot); 913 copySigningInfo(kextURL, 914 &hashString, 915 NULL, 916 NULL, 917 NULL); 918 } 919 else { 920 /* This is a signed Apple kext, but the root certificate is not Apple. 921 * This should not happen, so it is better to flag it as unsigned for 922 * collection purpose. */ 923 kextSigningCategory = CFSTR(kUnsignedKext); 924 copySigningInfo(kextURL, 925 &hashString, 926 &teamId, 927 NULL, 928 &issuerCN); 929 CFArrayRef subjectCNArray = NULL; // must release 930 subjectCNArray = copySubjectCNArray(kextURL); 931 if (subjectCNArray) { 932 subjectCN = CFStringCreateByCombiningStrings(kCFAllocatorDefault, 933 subjectCNArray, 934 CFSTR(";")); 935 SAFE_RELEASE(subjectCNArray); 936 } 937 } 938 } 939 else { 940 if (status == noErr) { 941 /* This 3rd-party kext is signed with a devid+ kext certificate */ 942 kextSigningCategory = CFSTR(k3rdPartyKextWithDevIdPlus); 943 copySigningInfo(kextURL, 944 &hashString, 945 &teamId, 946 &subjectCN, 947 &issuerCN); 948 } 949 else if (status == CSSMERR_TP_CERT_REVOKED) { 950 /* This 3rd-party kext is signed with a revoked devid+ kext certificate */ 951 kextSigningCategory = CFSTR(k3rdPartyKextWithRevokedDevIdPlus); 952 copySigningInfo(kextURL, 953 &hashString, 954 &teamId, 955 &subjectCN, 956 &issuerCN); 957 } 958 else { 959 status = checkRootCertificateIsApple(aKext); 960 if (status == noErr) { 961 /* This 3rd-party kext is not signed with a devid+ certificate, 962 * but uses an Apple root certificate. */ 963 kextSigningCategory = CFSTR(k3rdPartyKextWithAppleRoot); 964 /* The certificates may not have the expected format. 965 * Attempt to get the information if present, and also 966 * retrieve the subject cn of every certificate in the chain. */ 967 copySigningInfo(kextURL, 968 &hashString, 969 &teamId, 970 NULL, 971 &issuerCN); 972 CFArrayRef subjectCNArray = NULL; // must release 973 subjectCNArray = copySubjectCNArray(kextURL); 974 if (subjectCNArray) { 975 subjectCN = CFStringCreateByCombiningStrings(kCFAllocatorDefault, 976 subjectCNArray, 977 CFSTR(";")); 978 SAFE_RELEASE(subjectCNArray); 979 } 980 } 981 else { 982 /* This 3rd-party kext is not signed with a devid+ certificate, 983 * and does not use an Apple root certificate. */ 984 kextSigningCategory = CFSTR(k3rdPartyKextWithoutAppleRoot); 985 /* The certificates may not have the expected format. 986 * The subjectcn, issuercn and teamid must not be logged. */ 987 copySigningInfo(kextURL, 988 &hashString, 989 NULL, 990 NULL, 991 NULL); 992 } 993 } 994 } 995 } 996 997 kextDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 998 0, 999 &kCFTypeDictionaryKeyCallBacks, 1000 &kCFTypeDictionaryValueCallBacks); 1001 if (!kextDict) { 1002 OSKextLogMemError(); 1003 goto finish; 1004 } 1005 1006 if (bundleIDString) { 1007 CFDictionaryAddValue(kextDict, 1008 CFSTR(kMessageTracerBundleIDKey), 1009 bundleIDString); 1010 } 1011 if (versionString) { 1012 CFDictionaryAddValue(kextDict, 1013 CFSTR(kMessageTracerVersionKey), 1014 versionString); 1015 } 1016 if (filename) { 1017 CFDictionaryAddValue(kextDict, 1018 CFSTR(kMessageTracerKextNameKey), 1019 filename); 1020 } 1021 if (isFat != NULL) { 1022 CFDictionaryAddValue(kextDict, 1023 CFSTR(kMessageTracerFatKey), 1024 isFat); 1025 } 1026 if (archString) { 1027 CFDictionaryAddValue(kextDict, 1028 CFSTR(kMessageTracerArchKey), 1029 archString); 1030 } 1031 1032 if (kextSigningCategory) { 1033 CFDictionaryAddValue(kextDict, 1034 CFSTR(kMessageTracerSignatureTypeKey), 1035 kextSigningCategory); 1036 } 1037 1038 if (hashString) { 1039 CFDictionaryAddValue(kextDict, 1040 CFSTR(kMessageTracerHashKey), 1041 hashString); 1042 } 1043 1044 if (teamId) { 1045 CFDictionaryAddValue(kextDict, 1046 CFSTR(kMessageTracerTeamIdKey), 1047 teamId); 1048 } 1049 if (subjectCN) { 1050 CFDictionaryAddValue(kextDict, 1051 CFSTR(kMessageTracerSubjectCNKey), 1052 subjectCN); 1053 } 1054 if (issuerCN) { 1055 CFDictionaryAddValue(kextDict, 1056 CFSTR(kMessageTracerIssuerCNKey), 1057 issuerCN); 1058 } 1059 1060 if (kextPath) { 1061 CFDictionaryAddValue(kextDict, 1062 CFSTR(kMessageTracerPathKey), 1063 kextPath); 1064 } 1065 1066 1067 CFArrayAppendValue(*kextList, kextDict); 1068 1069finish: 1070 SAFE_FREE(hashCString); 1071 SAFE_RELEASE(kextURL); 1072 SAFE_RELEASE(kextPath); 1073 SAFE_RELEASE(filename); 1074 SAFE_RELEASE(hashString); 1075 SAFE_RELEASE(kextDict); 1076 SAFE_RELEASE(archString); 1077 SAFE_RELEASE(teamId); 1078 SAFE_RELEASE(subjectCN); 1079 SAFE_RELEASE(issuerCN); 1080 SAFE_RELEASE(code); 1081 SAFE_RELEASE(information); 1082 return; 1083} 1084 1085/******************************************************************************* 1086 * recordKextLoadListForMT() - record the list of loaded kexts 1087 * <rdar://problem/12435992> 1088 *******************************************************************************/ 1089void 1090recordKextLoadListForMT(CFArrayRef kextList) 1091{ 1092 CFIndex count, i; 1093 CFMutableArrayRef kextsToMessageTrace = NULL; //must release 1094 OSKextRef aKext; //do not release 1095 1096 if (kextList && (count = CFArrayGetCount(kextList))) { 1097 kextsToMessageTrace = CFArrayCreateMutable(kCFAllocatorDefault, 1098 CFArrayGetCount(kextList), 1099 &kCFTypeArrayCallBacks); 1100 if (kextsToMessageTrace) { 1101 for (i = 0; i < count; i ++) { 1102 aKext = (OSKextRef)CFArrayGetValueAtIndex(kextList, i); 1103 filterKextLoadForMT(aKext, &kextsToMessageTrace); 1104 } 1105 if (CFArrayGetCount(kextsToMessageTrace)) { 1106 postNoteAboutKextLoadsMT(CFSTR("Loaded Kext Notification"), 1107 kextsToMessageTrace); 1108 } 1109 SAFE_RELEASE(kextsToMessageTrace); 1110 } 1111 } 1112} 1113 1114/******************************************************************************* 1115 * recordKextLoadForMT() - record the loaded kext 1116 * <rdar://problem/12435992> 1117 *******************************************************************************/ 1118void recordKextLoadForMT(OSKextRef aKext) 1119{ 1120 CFMutableArrayRef myArray = NULL; // must release 1121 1122 if (!aKext) 1123 return; 1124 1125 myArray = CFArrayCreateMutable(kCFAllocatorDefault, 1126 1, 1127 &kCFTypeArrayCallBacks); 1128 if (myArray) { 1129 CFArrayAppendValue(myArray, aKext); 1130 recordKextLoadListForMT(myArray); 1131 SAFE_RELEASE(myArray); 1132 } 1133} 1134 1135/******************************************************************************* 1136 * checkKextSignature() - check the signature for given kext. 1137 *******************************************************************************/ 1138OSStatus checkKextSignature(OSKextRef aKext, Boolean checkExceptionList) 1139{ 1140 OSStatus result = -1; 1141 CFURLRef kextURL = NULL; // must release 1142 SecStaticCodeRef staticCodeRef = NULL; // must release 1143 SecRequirementRef requirementRef = NULL; // must release 1144 CFStringRef myCFString; 1145 CFStringRef requirementsString; 1146 1147 if (aKext == NULL) { 1148 return result; 1149 } 1150 1151 kextURL = CFURLCopyAbsoluteURL(OSKextGetURL(aKext)); 1152 if (!kextURL) { 1153 OSKextLogMemError(); 1154 goto finish; 1155 } 1156 1157 if (SecStaticCodeCreateWithPath(kextURL, 1158 kSecCSDefaultFlags, 1159 &staticCodeRef) != errSecSuccess || 1160 (staticCodeRef == NULL)) { 1161 OSKextLogMemError(); 1162 goto finish; 1163 } 1164 1165 /* set up correct requirement string. Apple kexts are signed by B&I while 1166 * 3rd party kexts are signed through a special developer kext devid 1167 * program 1168 */ 1169 myCFString = OSKextGetIdentifier(aKext); 1170 if (CFStringHasPrefix(myCFString, __kOSKextApplePrefix)) { 1171 requirementsString = CFSTR("anchor apple"); 1172 } 1173 else { 1174 /* DevID for kexts cert 1175 */ 1176 requirementsString = 1177 CFSTR("anchor apple generic " 1178 "and certificate 1[field.1.2.840.113635.100.6.2.6] " 1179 "and certificate leaf[field.1.2.840.113635.100.6.1.13] " 1180 "and certificate leaf[field.1.2.840.113635.100.6.1.18]" ); 1181 } 1182 1183 if (SecRequirementCreateWithString(requirementsString, 1184 kSecCSDefaultFlags, 1185 &requirementRef) != errSecSuccess || 1186 (requirementRef == NULL)) { 1187 OSKextLogMemError(); 1188 goto finish; 1189 } 1190 1191 // errSecCSUnsigned == -67062 1192 result = SecStaticCodeCheckValidity(staticCodeRef, 1193 kSecCSEnforceRevocationChecks, 1194 requirementRef); 1195 if ( result != 0 && 1196 checkExceptionList && 1197 isInExceptionList(aKext, true) ) { 1198 result = 0; 1199 } 1200 1201finish: 1202 SAFE_RELEASE(kextURL); 1203 SAFE_RELEASE(staticCodeRef); 1204 SAFE_RELEASE(requirementRef); 1205 1206 return result; 1207} 1208 1209#define GET_CSTRING_PTR(the_cfstring, the_ptr, the_buffer, the_size) \ 1210do { \ 1211the_ptr = CFStringGetCStringPtr(the_cfstring, kCFStringEncodingUTF8); \ 1212if (the_ptr == NULL) { \ 1213the_buffer[0] = 0x00; \ 1214the_ptr = the_buffer; \ 1215CFStringGetCString(the_cfstring, the_buffer, the_size, kCFStringEncodingUTF8); \ 1216} \ 1217} while(0) 1218 1219/********************************************************************* 1220 * isInExceptionList checks to see if the given kext is in the 1221 * kext signing exception list (in com.apple.driver.KextExcludeList). 1222 * If useCache is TRUE, we will use the cached copy of the exception list. 1223 * If useCache is FALSE, we will refresh the cache from disk. 1224 * 1225 * The kext signing exception list rarely changes but to insure you have the 1226 * most recent copy in the cache pass FALSE for the first call and TRUE for 1227 * subsequent calls (when dealing with a large list of kexts). 1228 * theKext can be NULL if you just want the invalidate the cache. 1229 *********************************************************************/ 1230Boolean isInExceptionList(OSKextRef theKext, Boolean useCache) 1231{ 1232 Boolean result = false; 1233 CFStringRef kextID = NULL; // must release 1234 OSKextRef excludelistKext = NULL; // must release 1235 CFDictionaryRef exceptionlistDict = NULL; // do NOT release 1236 static CFDictionaryRef myDictionary = NULL; // do NOT release 1237 1238 /* invalidate the cache or create it if not present */ 1239 if (useCache == false || myDictionary == NULL) { 1240 if (myDictionary != NULL) { 1241 SAFE_RELEASE_NULL(myDictionary); 1242 } 1243 kextID = CFStringCreateWithCString(kCFAllocatorDefault, 1244 "com.apple.driver.KextExcludeList", 1245 kCFStringEncodingUTF8); 1246 if (!kextID) { 1247 OSKextLogStringError(/* kext */ NULL); 1248 goto finish; 1249 } 1250 1251 excludelistKext = OSKextCreateWithIdentifier(kCFAllocatorDefault, 1252 kextID); 1253 if (!excludelistKext) { 1254 OSKextLog(/* kext */ NULL, 1255 kOSKextLogDebugLevel | kOSKextLogGeneralFlag, 1256 "Warning: %s could not find com.apple.driver.KextExcludeList", 1257 __FUNCTION__); 1258 goto finish; 1259 } 1260 1261 exceptionlistDict = OSKextGetValueForInfoDictionaryKey( 1262 excludelistKext, 1263 CFSTR("OSKextSigExceptionList")); 1264 if (!exceptionlistDict) { 1265 goto finish; 1266 } 1267 1268 if ((unsigned int)CFDictionaryGetCount(exceptionlistDict) > 0) { 1269 myDictionary = CFDictionaryCreateCopy(NULL, exceptionlistDict); 1270 } 1271 if (myDictionary == NULL) { 1272 OSKextLogMemError(); 1273 goto finish; 1274 } 1275 } 1276 if (theKext == NULL) { 1277 goto finish; 1278 } 1279 1280 /********************************************************************* 1281 * myDictionary is a dictionary with keys / values of: 1282 * key = bundleID string of kext we will allow to load inspite of signing 1283 * failure. 1284 * value = version string of kext to allow to load. 1285 * The value is used to check equal or less than a kext with a matching 1286 * version string. For example if an entry in the list has key: 1287 * com.foocompany.fookext 1288 * and value: 1289 * 4.2.10 1290 * Then any kext with bundle ID of com.foocompany.fookext and a version 1291 * string of 4.2.10 or less will be allowed to load even if there is a 1292 * a kext signing validation failure. 1293 * 1294 * NOTE - Kext versions use an extended Mac OS 'vers' format with double 1295 * the number of digits before the build stage: ####.##.##s{1-255} where 's' 1296 * is a build stage 'd', 'a', 'b', 'f' or 'fc'. We parse this with 1297 * OSKextParseVersionString 1298 *********************************************************************/ 1299 CFStringRef bundleID = NULL; // do NOT release 1300 CFStringRef exceptionKextVersString = NULL; // do NOT release 1301 OSKextVersion kextVers = -1; 1302 const char * versCString = NULL; // do not free 1303 OSKextVersion exceptionKextVers; 1304 char versBuffer[256]; 1305 1306 bundleID = OSKextGetIdentifier(theKext); 1307 if (!bundleID) { 1308 OSKextLog(/* kext */ NULL, 1309 kOSKextLogDebugLevel | kOSKextLogGeneralFlag, 1310 "%s could not get bundleID", 1311 __FUNCTION__); 1312 goto finish; 1313 } 1314 1315 kextVers = OSKextGetVersion(theKext); 1316 if (!kextVers) { 1317 OSKextLog(/* kext */ NULL, 1318 kOSKextLogDebugLevel | kOSKextLogGeneralFlag, 1319 "%s could not get kextVers", 1320 __FUNCTION__); 1321 goto finish; 1322 } 1323 1324 exceptionKextVersString = CFDictionaryGetValue(myDictionary, bundleID); 1325 if (!exceptionKextVersString) { 1326 goto finish; 1327 } 1328 1329 /* parse version strings */ 1330 GET_CSTRING_PTR(exceptionKextVersString, 1331 versCString, 1332 versBuffer, 1333 sizeof(versBuffer)); 1334 if (strlen(versCString) < 1) { 1335 goto finish; 1336 } 1337 1338 exceptionKextVers = OSKextParseVersionString(versCString); 1339 if (kextVers <= exceptionKextVers) { 1340 OSKextLogCFString(NULL, 1341 kOSKextLogGeneralFlag | kOSKextLogErrorLevel, 1342 CFSTR("kext %@ %lld is in exception list, allowing to load"), 1343 bundleID, kextVers); 1344 result = true; 1345 } 1346 1347finish: 1348 SAFE_RELEASE(kextID); 1349 SAFE_RELEASE(excludelistKext); 1350 return result; 1351} 1352 1353/******************************************************************************* 1354 * isDebugSetInBootargs() - check to see if boot-args has debug set. We cache 1355 * the result since boot-args / debug will not change until reboot. 1356 *******************************************************************************/ 1357Boolean isDebugSetInBootargs(void) 1358{ 1359 static int didOnce = 0; 1360 static Boolean result = false; 1361 io_registry_entry_t optionsNode = MACH_PORT_NULL; // must release 1362 CFStringRef bootargsEntry = NULL; // must release 1363 1364 if (didOnce) { 1365 return(result); 1366 } 1367 optionsNode = IORegistryEntryFromPath(kIOMasterPortDefault, 1368 "IODeviceTree:/options"); 1369 if (optionsNode) { 1370 bootargsEntry = (CFStringRef) 1371 IORegistryEntryCreateCFProperty(optionsNode, 1372 CFSTR("boot-args"), 1373 kCFAllocatorDefault, 0); 1374 if (bootargsEntry && 1375 (CFGetTypeID(bootargsEntry) == CFStringGetTypeID())) { 1376 CFRange findRange; 1377 findRange = CFStringFind(bootargsEntry, CFSTR("debug"), 0); 1378 1379 if (findRange.length != 0) { 1380 result = true; 1381 } 1382 } 1383 } 1384 didOnce++; 1385 if (optionsNode) IOObjectRelease(optionsNode); 1386 SAFE_RELEASE(bootargsEntry); 1387 1388 return(result); 1389} 1390 1391 1392/********************************************************************* 1393 *********************************************************************/ 1394Boolean isInLibraryExtensionsFolder(OSKextRef theKext) 1395{ 1396 CFStringRef myKextPath = NULL; // must release 1397 Boolean myResult = false; 1398 1399 myKextPath = copyKextPath(theKext); 1400 if ( myKextPath ) { 1401 if ( CFStringHasPrefix(myKextPath, 1402 CFSTR(_kOSKextLibraryExtensionsFolder)) ) { 1403 myResult = true; 1404 } 1405 } 1406 SAFE_RELEASE(myKextPath); 1407 return(myResult); 1408} 1409 1410 1411 1412