1/* 2 * Copyright (c) 2008 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#include <IOKit/IOKitLib.h> 29#include <IOKit/IOKitServer.h> 30#include <IOKit/kext/OSKextPrivate.h> 31#include <IOKit/IOCFSerialize.h> 32 33#include <sys/stat.h> 34#include <sys/mman.h> 35#include <libc.h> 36#include <zlib.h> 37 38#include "kextd_main.h" 39#include "kextd_personalities.h" 40#include "kextd_usernotification.h" 41#include "kextd_globals.h" 42 43static OSReturn sendCachedPersonalitiesToKernel(Boolean resetFlag); 44 45/******************************************************************************* 46*******************************************************************************/ 47OSReturn sendSystemKextPersonalitiesToKernel( 48 CFArrayRef kexts, 49 Boolean resetFlag) 50{ 51 OSReturn result = kOSReturnSuccess; // optimistic 52 CFArrayRef personalities = NULL; // must release 53 CFMutableArrayRef authenticKexts = NULL; // must release 54 CFIndex count, i; 55 56 /* Note that we are going to finish on success here! 57 * If we sent personalities we are done. 58 * sendCachedPersonalitiesToKernel() logs a msg on failure. 59 */ 60 result = sendCachedPersonalitiesToKernel(resetFlag); 61 if (result == kOSReturnSuccess) { 62 goto finish; 63 } 64 65 /* If we didn't send from cache, send from the kexts. This will cause 66 * lots of I/O. 67 */ 68 if (!createCFMutableArray(&authenticKexts, &kCFTypeArrayCallBacks)) { 69 OSKextLogMemError(); 70 goto finish; 71 } 72 73 /* Check all the kexts to see if we need to raise alerts 74 * about improperly-installed extensions. 75 */ 76 recordNonsecureKexts(kexts); 77 78 count = CFArrayGetCount(kexts); 79 for (i = 0; i < count; i++) { 80 OSKextRef aKext = (OSKextRef)CFArrayGetValueAtIndex(kexts, i); 81 if (OSKextIsAuthentic(aKext)) { 82 CFArrayAppendValue(authenticKexts, aKext); 83 } 84 } 85 86 result = OSKextSendPersonalitiesOfKextsToKernel(authenticKexts, 87 resetFlag); 88 if (result != kOSReturnSuccess) { 89 goto finish; 90 } 91 92 personalities = OSKextCopyPersonalitiesOfKexts(authenticKexts); 93 94 /* Now try to write the cache file. Don't save the return value 95 * of that function, we're more concerned with whether personalities 96 * have actually gone to the kernel. 97 */ 98 _OSKextWriteCache(OSKextGetSystemExtensionsFolderURLs(), 99 CFSTR(kIOKitPersonalitiesKey), gKernelArchInfo, 100 _kOSKextCacheFormatIOXML, personalities); 101 102finish: 103 if (result != kOSReturnSuccess) { 104 OSKextLog(/* kext */ NULL, 105 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 106 "Error: Couldn't send kext personalities to the IOCatalogue."); 107 } else if (personalities) { 108 OSKextLog(/* kext */ NULL, 109 kOSKextLogProgressLevel | kOSKextLogIPCFlag | 110 kOSKextLogKextBookkeepingFlag, 111 "Sent %ld kext personalities to the IOCatalogue.", 112 CFArrayGetCount(personalities)); 113 } 114 SAFE_RELEASE(personalities); 115 SAFE_RELEASE(authenticKexts); 116 return result; 117} 118 119/******************************************************************************* 120*******************************************************************************/ 121static OSReturn sendCachedPersonalitiesToKernel(Boolean resetFlag) 122{ 123 OSReturn result = kOSReturnError; 124 CFDataRef cacheData = NULL; // must release 125 126 if (!_OSKextReadCache(gRepositoryURLs, CFSTR(kIOKitPersonalitiesKey), 127 gKernelArchInfo, _kOSKextCacheFormatIOXML, 128 /* parseXML? */ false, (CFPropertyListRef *)&cacheData)) { 129 130 goto finish; 131 } 132 133 OSKextLogCFString(/* kext */ NULL, 134 kOSKextLogProgressLevel | kOSKextLogIPCFlag | 135 kOSKextLogKextBookkeepingFlag, 136 CFSTR("%@"), CFSTR("Sending cached kext personalities to IOCatalogue.")); 137 138 result = IOCatalogueSendData(kIOMasterPortDefault, 139 resetFlag ? kIOCatalogResetDrivers : kIOCatalogAddDrivers, 140 (char *)CFDataGetBytePtr(cacheData), (unsigned int)CFDataGetLength(cacheData)); 141 if (result != kOSReturnSuccess) { 142 OSKextLog(/* kext */ NULL, 143 kOSKextLogErrorLevel | kOSKextLogIPCFlag, 144 "error: couldn't send personalities to the kernel."); 145 goto finish; 146 } 147 148 OSKextLogCFString(/* kext */ NULL, 149 kOSKextLogProgressLevel | kOSKextLogIPCFlag | 150 kOSKextLogKextBookkeepingFlag, 151 CFSTR("%@"), CFSTR("Sent cached kext personalities to the IOCatalogue.")); 152 153 result = kOSReturnSuccess; 154 155finish: 156 SAFE_RELEASE(cacheData); 157 return result; 158} 159 160