#ifndef _LIBKERN_OSKEXT_H
#define _LIBKERN_OSKEXT_H
extern "C" {
#include <kern/thread_call.h>
#include <libkern/OSKextLibPrivate.h>
#include <libkern/kernel_mach_header.h>
#include <libkern/kxld.h>
#include <mach/kmod.h>
#ifdef XNU_KERNEL_PRIVATE
#include <kern/thread_call.h>
#endif
}
#include <libkern/OSKextLib.h>
#include <libkern/OSKextLibPrivate.h>
#include <libkern/c++/OSObject.h>
#include <libkern/c++/OSContainers.h>
#include <IOKit/IOLocks.h>
#ifdef XNU_KERNEL_PRIVATE
extern "C" {
void osdata_kmem_free(void * ptr, unsigned int length);
void osdata_phys_free(void * ptr, unsigned int length);
void osdata_vm_deallocate(void * ptr, unsigned int length);
void osdata_kext_free(void * ptr, unsigned int length);
void kxld_log_callback(
KXLDLogSubsystem subsystem,
KXLDLogLevel level,
const char * format,
va_list argList,
void * user_data);
};
#endif
class OSKext;
extern "C" {
void OSKextLog(
OSKext * aKext,
OSKextLogSpec msgLogSpec,
const char * format, ...)
__attribute__((format(printf, 3, 4)));
void OSKextVLog(
OSKext * aKext,
OSKextLogSpec msgLogSpec,
const char * format,
va_list srcArgList);
#ifdef XNU_KERNEL_PRIVATE
void OSKextRemoveKextBootstrap(void);
kern_return_t OSRuntimeInitializeCPP(
OSKext * kext);
kern_return_t OSRuntimeFinalizeCPP(
OSKext * kext);
void OSRuntimeUnloadCPPForSegment(
kernel_segment_command_t * segment);
kern_return_t is_io_catalog_send_data(
mach_port_t masterPort,
uint32_t flag,
io_buf_ptr_t inData,
mach_msg_type_number_t inDataCount,
kern_return_t * result);
void kmod_dump_log(vm_offset_t*, unsigned int, boolean_t);
void *OSKextKextForAddress(const void *addr);
#endif
};
#if PRAGMA_MARK
#pragma mark -
#endif
struct list_head {
struct list_head *prev;
struct list_head *next;
};
struct OSKextGrabPgoStruct {
bool metadata;
uint64_t *pSize;
char *pBuffer;
uint64_t bufferSize;
int err;
struct list_head list_head;
};
#ifndef container_of
#define container_of(ptr,type,member) ((type*)(((uintptr_t)ptr) - offsetof(type, member)))
#endif
#if XNU_KERNEL_PRIVATE
struct OSKextAccount
{
vm_allocation_site_t site;
uint32_t loadTag;
OSKext * kext;
};
struct OSKextActiveAccount
{
uintptr_t address;
uintptr_t address_end;
OSKextAccount * account;
};
typedef struct OSKextActiveAccount OSKextActiveAccount;
#endif
class OSKext : public OSObject
{
OSDeclareDefaultStructors(OSKext)
#if PRAGMA_MARK
#pragma mark Friend Declarations
#endif
friend class IOCatalogue;
friend class KLDBootstrap;
friend class OSMetaClass;
friend int OSKextGrabPgoData(uuid_t uuid,
uint64_t *pSize,
char *pBuffer,
uint64_t bufferSize,
int wait_for_unload,
int metadata);
#ifdef XNU_KERNEL_PRIVATE
friend void OSKextVLog(
OSKext * aKext,
OSKextLogSpec msgLogSpec,
const char * format,
va_list srcArgList);
friend void OSKextRemoveKextBootstrap(void);
friend OSReturn OSKextUnloadKextWithLoadTag(uint32_t);
friend kern_return_t kext_request(
host_priv_t hostPriv,
uint32_t clientLogSpec,
vm_offset_t requestIn,
mach_msg_type_number_t requestLengthIn,
vm_offset_t * responseOut,
mach_msg_type_number_t * responseLengthOut,
vm_offset_t * logDataOut,
mach_msg_type_number_t * logDataLengthOut,
kern_return_t * op_result);
friend kxld_addr_t kern_allocate(
u_long size,
KXLDAllocateFlags * flags,
void * user_data);
friend void kxld_log_shim(
KXLDLogSubsystem subsystem,
KXLDLogLevel level,
const char * format,
va_list argList,
void * user_data);
friend void _OSKextConsiderUnloads(
__unused thread_call_param_t p0,
__unused thread_call_param_t p1);
friend kern_return_t OSRuntimeInitializeCPP(
OSKext * kext);
friend kern_return_t OSRuntimeFinalizeCPP(
OSKext * kext);
friend void OSRuntimeUnloadCPPForSegment(
kernel_segment_command_t * segment);
friend kern_return_t is_io_catalog_send_data(
mach_port_t masterPort,
uint32_t flag,
io_buf_ptr_t inData,
mach_msg_type_number_t inDataCount,
kern_return_t * result);
friend void kmod_panic_dump(vm_offset_t*, unsigned int);
friend void kmod_dump_log(vm_offset_t*, unsigned int, boolean_t);
friend void kext_dump_panic_lists(int (*printf_func)(const char * fmt, ...));
friend void *OSKextKextForAddress(const void *addr);
#endif
private:
OSDictionary * infoDict;
const OSSymbol * bundleID;
OSString * path; OSString * executableRelPath;
OSKextVersion version; OSKextVersion compatibleVersion;
OSKextLoadTag loadTag; kmod_info_t * kmod_info;
OSArray * dependencies;
OSData * linkedExecutable;
OSSet * metaClasses;
OSData * interfaceUUID;
struct {
unsigned int loggingEnabled:1;
unsigned int hasAllDependencies:1;
unsigned int hasBleedthrough:1;
unsigned int interface:1;
unsigned int kernelComponent:1;
unsigned int prelinked:1;
unsigned int builtin:1;
unsigned int loaded:1;
unsigned int dtraceInitialized:1;
unsigned int starting:1;
unsigned int started:1;
unsigned int stopping:1;
unsigned int unloading:1;
unsigned int autounloadEnabled:1;
unsigned int delayAutounload:1;
unsigned int CPPInitialized:1;
unsigned int jettisonLinkeditSeg:1;
} flags;
struct list_head pendingPgoHead;
uuid_t instance_uuid;
OSKextAccount * account;
uint32_t builtinKmodIdx;
#if PRAGMA_MARK
#pragma mark Private Functions
#endif
#ifdef XNU_KERNEL_PRIVATE
public:
static void initialize(void);
static OSDictionary * copyKexts(void);
static OSReturn removeKextBootstrap(void);
static void willShutdown(void); static void reportOSMetaClassInstances(
const char * kextIdentifier,
OSKextLogSpec msgLogSpec);
#endif
private:
static bool setLoadEnabled(bool flag);
static bool setUnloadEnabled(bool flag);
static bool setAutounloadsEnabled(bool flag);
static bool setKernelRequestsEnabled(bool flag);
static bool getLoadEnabled(void);
static bool getUnloadEnabled(void);
static bool getAutounloadEnabled(void);
static bool getKernelRequestsEnabled(void);
static OSKext * withBooterData(
OSString * deviceTreeName,
OSData * booterData);
virtual bool initWithBooterData(
OSString * deviceTreeName,
OSData * booterData);
static OSKext * withPrelinkedInfoDict(
OSDictionary * infoDict,
bool doCoalesedSlides);
virtual bool initWithPrelinkedInfoDict(
OSDictionary * infoDict,
bool doCoalesedSlides);
static void setAllVMAttributes(void);
static OSKext * withMkext2Info(
OSDictionary * anInfoDict,
OSData * mkextData);
virtual bool initWithMkext2Info(
OSDictionary * anInfoDict,
OSData * mkextData);
virtual bool setInfoDictionaryAndPath(
OSDictionary * aDictionary,
OSString * aPath);
virtual bool setExecutable(
OSData * anExecutable,
OSData * externalData = NULL,
bool externalDataIsMkext = false);
virtual bool registerIdentifier(void);
virtual void free(void) APPLE_KEXT_OVERRIDE;
static OSReturn removeKext(
OSKext * aKext,
bool terminateServicesAndRemovePersonalitiesFlag = false);
virtual bool isInExcludeList(void);
static OSReturn readMkextArchive(
OSData * mkextData,
uint32_t * checksumPtr = NULL);
static OSReturn readMkext2Archive(
OSData * mkextData,
OSDictionary ** mkextPlistOut,
uint32_t * checksumPtr = NULL);
virtual OSData * createMkext2FileEntry(
OSData * mkextData,
OSNumber * offsetNum,
const char * entryName);
virtual OSData * extractMkext2FileData(
UInt8 * data,
const char * name,
uint32_t compressedSize,
uint32_t fullSize);
virtual bool resolveDependencies(
OSArray * loopStack = NULL); virtual bool addBleedthroughDependencies(OSArray * anArray);
virtual bool flushDependencies(bool forceFlag = false); virtual uint32_t getNumDependencies(void);
virtual OSArray * getDependencies(void);
static OSReturn loadFromMkext(
OSKextLogSpec clientLogSpec,
char * mkextBuffer,
uint32_t mkextBufferLength,
char ** logInfoOut,
uint32_t * logInfoLengthOut);
static OSReturn handleRequest(
host_priv_t hostPriv,
OSKextLogSpec clientLogSpec,
char * requestBuffer,
uint32_t requestLength,
char ** responseOut,
uint32_t * responseLengthOut,
char ** logInfoOut,
uint32_t * logInfoLengthOut);
static OSReturn serializeLogInfo(
OSArray * logInfoArray,
char ** logInfoOut,
uint32_t * logInfoLengthOut);
virtual OSReturn load(
OSKextExcludeLevel startOpt = kOSKextExcludeNone,
OSKextExcludeLevel startMatchingOpt = kOSKextExcludeAll,
OSArray * personalityNames = NULL); virtual OSReturn unload(void);
virtual OSReturn queueKextNotification(
const char * notificationName,
OSString * kextIdentifier);
static void recordIdentifierRequest(
OSString * kextIdentifier);
virtual OSReturn slidePrelinkedExecutable(bool doCoalesedSlides);
virtual OSReturn loadExecutable(void);
virtual void jettisonLinkeditSegment(void);
virtual void jettisonDATASegmentPadding(void);
static void considerDestroyingLinkContext(void);
virtual OSData * getExecutable(void);
virtual void setLinkedExecutable(OSData * anExecutable);
#if CONFIG_DTRACE
friend void OSKextRegisterKextsWithDTrace(void);
static void registerKextsWithDTrace(void);
virtual void registerWithDTrace(void);
virtual void unregisterWithDTrace(void);
#endif
virtual OSReturn start(bool startDependenciesFlag = true);
virtual OSReturn stop(void);
virtual OSReturn setVMAttributes(bool protect, bool wire);
virtual boolean_t segmentShouldBeWired(kernel_segment_command_t *seg);
virtual OSReturn validateKextMapping(bool startFlag);
virtual boolean_t verifySegmentMapping(kernel_segment_command_t *seg);
static OSArray * copyAllKextPersonalities(
bool filterSafeBootFlag = false);
static void setPrelinkedPersonalities(OSArray * personalitiesArray);
static void sendAllKextPersonalitiesToCatalog(
bool startMatching = false);
virtual OSReturn sendPersonalitiesToCatalog(
bool startMatching = false,
OSArray * personalityNames = NULL);
static bool canUnloadKextWithIdentifier(
OSString * kextIdentifier,
bool checkClassesFlag = true);
static OSReturn autounloadKext(OSKext * aKext);
static OSReturn pingKextd(void);
static OSDictionary * copyLoadedKextInfo(
OSArray * kextIdentifiers = NULL,
OSArray * keys = NULL);
static OSDictionary * copyLoadedKextInfoByUUID(
OSArray * kextIdentifiers = NULL,
OSArray * keys = NULL);
static OSData * copyKextUUIDForAddress(OSNumber *address = NULL);
virtual OSDictionary * copyInfo(OSArray * keys = NULL);
static OSKextLogSpec setUserSpaceLogFilter(
OSKextLogSpec userLogSpec,
bool captureFlag = false);
static OSArray * clearUserSpaceLogFilter(void);
static OSKextLogSpec getUserSpaceLogFilter(void);
virtual OSReturn addClass(
OSMetaClass * aClass,
uint32_t numClasses);
virtual OSReturn removeClass(
OSMetaClass * aClass);
virtual bool hasOSMetaClassInstances(void);
virtual OSSet * getMetaClasses(void);
virtual void reportOSMetaClassInstances(
OSKextLogSpec msgLogSpec);
static OSReturn dispatchResource(OSDictionary * requestDict);
static OSReturn dequeueCallbackForRequestTag(
OSKextRequestTag requestTag,
OSDictionary ** callbackRecordOut);
static OSReturn dequeueCallbackForRequestTag(
OSNumber * requestTagNum,
OSDictionary ** callbackRecordOut);
static void invokeRequestCallback(
OSDictionary * callbackRecord,
OSReturn requestResult);
virtual void invokeOrCancelRequestCallbacks(
OSReturn callbackResult,
bool invokeFlag = true);
virtual uint32_t countRequestCallbacks(void);
public:
enum {
kPrintKextsLock = 0x01,
kPrintKextsUnslide = 0x02,
kPrintKextsTerse = 0x04
};
static void printKextsInBacktrace(
vm_offset_t * addr,
unsigned int cnt,
int (* printf_func)(const char *fmt, ...),
uint32_t flags);
private:
static OSKextLoadedKextSummary *summaryForAddress(const uintptr_t addr);
static void *kextForAddress(const void *addr);
static boolean_t summaryIsInBacktrace(
OSKextLoadedKextSummary * summary,
vm_offset_t * addr,
unsigned int cnt);
static void printSummary(
OSKextLoadedKextSummary * summary,
int (* printf_func)(const char *fmt, ...),
uint32_t flags);
static int saveLoadedKextPanicListTyped(
const char * prefix,
int invertFlag,
int libsFlag,
char * paniclist,
uint32_t list_size);
static void saveLoadedKextPanicList(void);
void savePanicString(bool isLoading);
static void printKextPanicLists(int (*printf_func)(const char *fmt, ...));
static void updateLoadedKextSummaries(void);
void updateLoadedKextSummary(OSKextLoadedKextSummary *summary);
void updateActiveAccount(OSKextActiveAccount *accountp);
#ifdef XNU_KERNEL_PRIVATE
public:
#endif
virtual void setCPPInitialized(bool initialized=true);
#if PRAGMA_MARK
#pragma mark Public Functions
#endif
public:
static OSKext * lookupKextWithIdentifier(const char * kextIdentifier);
static OSKext * lookupKextWithIdentifier(OSString * kextIdentifier);
static OSKext * lookupKextWithLoadTag(OSKextLoadTag aTag);
static OSKext * lookupKextWithAddress(vm_address_t address);
static OSKext * lookupKextWithUUID(uuid_t uuid);
kernel_section_t *lookupSection(const char *segname, const char*secname);
static bool isKextWithIdentifierLoaded(const char * kextIdentifier);
static OSReturn loadKextWithIdentifier(
const char * kextIdentifier,
Boolean allowDeferFlag = true,
Boolean delayAutounloadFlag = false,
OSKextExcludeLevel startOpt = kOSKextExcludeNone,
OSKextExcludeLevel startMatchingOpt = kOSKextExcludeAll,
OSArray * personalityNames = NULL);
static OSReturn loadKextWithIdentifier(
OSString * kextIdentifier,
Boolean allowDeferFlag = true,
Boolean delayAutounloadFlag = false,
OSKextExcludeLevel startOpt = kOSKextExcludeNone,
OSKextExcludeLevel startMatchingOpt = kOSKextExcludeAll,
OSArray * personalityNames = NULL);
static OSReturn removeKextWithIdentifier(
const char * kextIdentifier,
bool terminateServicesAndRemovePersonalitiesFlag = false);
static OSReturn removeKextWithLoadTag(
OSKextLoadTag loadTag,
bool terminateServicesAndRemovePersonalitiesFlag = false);
static OSReturn requestResource(
const char * kextIdentifier,
const char * resourceName,
OSKextRequestResourceCallback callback,
void * context,
OSKextRequestTag * requestTagOut);
static OSReturn cancelRequest(
OSKextRequestTag requestTag,
void ** contextOut);
static void considerUnloads(Boolean rescheduleOnlyFlag = false);
static void flushNonloadedKexts(Boolean flushPrelinkedKexts);
static void setKextdActive(Boolean active = true);
static void setDeferredLoadSucceeded(Boolean succeeded = true);
static void considerRebuildOfPrelinkedKernel(void);
static void createExcludeListFromBooterData(
OSDictionary * theDictionary,
OSCollectionIterator * theIterator);
static void createExcludeListFromPrelinkInfo(OSArray * theInfoArray);
static boolean_t updateExcludeList(OSDictionary * infoDict);
static bool isWaitingKextd(void);
virtual bool setAutounloadEnabled(bool flag);
virtual const OSSymbol * getIdentifier(void);
virtual const char * getIdentifierCString(void);
virtual OSKextVersion getVersion(void);
virtual OSKextVersion getCompatibleVersion(void);
virtual bool isLibrary(void);
virtual bool isCompatibleWithVersion(OSKextVersion aVersion);
virtual OSObject * getPropertyForHostArch(const char * key);
virtual OSKextLoadTag getLoadTag(void);
virtual void getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize);
virtual OSData * copyUUID(void);
OSData * copyTextUUID(void);
OSData * copyMachoUUID(const kernel_mach_header_t * header);
virtual OSArray * copyPersonalitiesArray(void);
virtual void removePersonalitiesFromCatalog(void);
static void uniquePersonalityProperties(OSDictionary * personalityDict);
virtual bool declaresExecutable(void); virtual bool isInterface(void);
virtual bool isKernel(void);
virtual bool isKernelComponent(void);
virtual bool isExecutable(void);
virtual bool isLoadableInSafeBoot(void);
virtual bool isPrelinked(void);
virtual bool isLoaded(void);
virtual bool isStarted(void);
virtual bool isCPPInitialized(void);
};
#endif