Search code examples
objective-ccmacoskernelkernel-extension

Getting Bundle Identifier for KEXT from .kext Directory Programmatically


I'm building a kernel extension and having a .kext directory for it. From another library API, I'm using KextManager APIs to load this kext into kernel.

Everything looks fine, here is the code piece that I'm loading the kext with:

CFStringRef path = CFStringCreateWithCString(kCFAllocatorDefault, "awesome.kext", kCFStringEncodingUTF8);
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, true);
OSReturn result  = KextManagerLoadKextWithURL(url, NULL);

It works great, however I need to know my bundle identifier to have control socket connection, and maybe unload the kext with KextManagerUnloadKextWithIdentifier(kextId) API later.

So I'm aware of XXX.kext/Contents/Info.plist which contains CFBundleIdentifier key with bundle identifier but I need some way of getting it programmatically (some API?) instead of reading Info.plist file and parsing it.

I also tried to replace CFBundleIdentifier string value with something else and load into kernel, it still works fine, so it looks like Info.plist is not reliable anyway.

Is there anything related? Any suggestions? Thanks! :)


Solution

  • I discovered 2 useful approaches recently, both based on KextManagerCopyLoadedKextInfo API.

    void handle_kext(const void* key, const void* value, void* context)
    {
        // OSBundlePath - CFString (this is merely a hint stored in the kernel; the kext is not guaranteed to be at this path)
        CFStringRef bundle_path_key = CFStringCreateWithCString(kCFAllocatorDefault, "OSBundlePath", kCFStringEncodingUTF8);
    
        const char* bundle_id_cstring = CFStringGetCStringPtr(key, kCFStringEncodingUTF8);
        const char* bundle_path_cstring = CFStringGetCStringPtr(CFDictionaryGetValue(value, bundle_path_key, kCFStringEncodingUTF8);
    
        // #1 Approach: Compare your 'I-Want-This-BundleID' with loaded kext path
        // #2 Approach: Compare your 'I-Want-This-BundlePath' with loaded kext ID
    }
    
    void some_func()
    {
        CFDictionaryRef loaded_kexts = KextManagerCopyLoadedKextInfo(NULL, NULL);
        CFDictionaryApplyFunction(loaded_kexts, handle_kext, NULL);
    }