kextd_personalities.c [plain text]
#include <IOKit/IOKitLib.h>
#include <IOKit/IOKitServer.h>
#include <IOKit/kext/OSKextPrivate.h>
#include <IOKit/IOCFSerialize.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <libc.h>
#include <zlib.h>
#include "kextd_main.h"
#include "kextd_personalities.h"
#include "kextd_usernotification.h"
#include "kextd_globals.h"
OSReturn sendDirectoryPersonaltiesToKernel(
CFURLRef directoryURL,
const NXArchInfo * arch);
OSReturn sendCachedPersonalitiesToKernel(
CFURLRef folderURL,
const NXArchInfo * arch);
OSReturn sendPersonalitiesToKernel(void)
{
OSReturn result = kOSReturnSuccess; CFArrayRef systemExtensionsFolderURLs = NULL; CFIndex count, i;
systemExtensionsFolderURLs = OSKextGetSystemExtensionsFolderURLs();
if (!systemExtensionsFolderURLs ||
!CFArrayGetCount(systemExtensionsFolderURLs)) {
result = kOSReturnError;
goto finish;
}
count = CFArrayGetCount(systemExtensionsFolderURLs);
for (i = 0; i < count; i++) {
OSReturn directoryResult = sendDirectoryPersonaltiesToKernel(
CFArrayGetValueAtIndex(systemExtensionsFolderURLs, i),
gKernelArchInfo);
if (directoryResult != kOSReturnSuccess) {
result = kOSReturnError;
}
}
finish:
return result;
}
OSReturn sendDirectoryPersonaltiesToKernel(
CFURLRef directoryURL,
const NXArchInfo * arch)
{
OSReturn result = kOSReturnError;
char directoryPath[PATH_MAX] = "";
CFArrayRef kexts = NULL; CFMutableArrayRef authenticKexts = NULL; CFIndex count, i;
if (!CFURLGetFileSystemRepresentation(directoryURL,
true, (UInt8 *)directoryPath, sizeof(directoryPath))) {
OSKextLogStringError( NULL);
goto finish;
}
result = sendCachedPersonalitiesToKernel(directoryURL, arch);
if (result == kOSReturnSuccess) {
goto finish;
}
kexts = OSKextCreateKextsFromURL(kCFAllocatorDefault, directoryURL);
if (!kexts) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Can't read kexts from %s.", directoryPath);
goto finish;
}
if (!createCFMutableArray(&authenticKexts, &kCFTypeArrayCallBacks)) {
OSKextLogMemError();
goto finish;
}
recordNonsecureKexts(kexts);
count = CFArrayGetCount(kexts);
for (i = 0; i < count; i++) {
OSKextRef aKext = (OSKextRef)CFArrayGetValueAtIndex(kexts, i);
if (OSKextIsAuthentic(aKext)) {
CFArrayAppendValue(authenticKexts, aKext);
}
}
result = OSKextSendPersonalitiesOfKextsToKernel(authenticKexts);
if (result != kOSReturnSuccess) {
goto finish;
}
writePersonalitiesCache(authenticKexts, gKernelArchInfo,
directoryURL);
finish:
SAFE_RELEASE(kexts);
SAFE_RELEASE(authenticKexts);
return result;
}
OSReturn sendCachedPersonalitiesToKernel(
CFURLRef folderURL,
const NXArchInfo * arch)
{
OSReturn result = kOSReturnError;
CFDataRef cacheData = NULL; char folderPath[PATH_MAX] = "";
if (!CFURLGetFileSystemRepresentation(folderURL,
true, (UInt8 *)folderPath, sizeof(folderPath))) {
OSKextLogStringError( NULL);
goto finish;
}
if (!_OSKextReadCache(folderURL, CFSTR(kIOKitPersonalitiesKey),
arch, _kOSKextCacheFormatIOXML, false,
(CFPropertyListRef *)&cacheData)) {
goto finish;
}
OSKextLog( NULL,
kOSKextLogProgressLevel | kOSKextLogIPCFlag |
kOSKextLogKextBookkeepingFlag,
"Sending cached personalities for %s to IOCatalogue.",
folderPath);
result = IOCatalogueSendData(kIOMasterPortDefault, kIOCatalogAddDrivers,
(char *)CFDataGetBytePtr(cacheData), CFDataGetLength(cacheData));
if (result != kOSReturnSuccess) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogIPCFlag,
"error: couldn't send personalities to the kernel");
goto finish;
} else {
OSKextLog( NULL,
kOSKextLogProgressLevel | kOSKextLogIPCFlag |
kOSKextLogKextBookkeepingFlag,
"Sent cached personalities for %s to the IOCatalogue.",
folderPath);
}
result = kOSReturnSuccess;
finish:
SAFE_RELEASE(cacheData);
return result;
}