The Anatomy of a Kernel Extension
Kexts are loadable bundles, and like all loadable bundles, they are loaded dynamically by another application. In the case of a kext, this application is the kernel itself. This has many implications for kexts, such as running in supervisor mode and the ability to load during early boot. Kexts have strict security and location requirements that you need to follow for your kext to work.
To understand the anatomy of a kext, you should have a basic understanding of bundles. For general information on the structure of a bundle, see Bundle Programming Guide.
A Kext Bundle Usually Contains Two Main Components
In the most general case, a kext bundle contains two components: an information property list and an executable. Along with these components, a kext bundle may include additional resources and plug-ins. Each of these components is described here.
The Information Property List
Info.plist file describes the kext’s contents. Every kext must have an
Info.plist file. Because a kext can be loaded during early boot when limited processing is available, this file must be in XML format and cannot include comments. The following keys are of particular importance in a kext’s
CFBundleIdentifieris used to locate a kext both on disk and in the kernel. Multiple kexts with a given identifier can exist on disk, but only one such kext can be loaded in the kernel at a time.
CFBundleExecutablespecifies the name of your kext’s executable, if it has one.
CFBundleVersionindicates the kext’s version. Kext version numbers follow a strict pattern (see Info.plist Properties for Kernel Extensions).
OSBundleLibrarieslists the libraries (which are kexts themselves) that the kext links against.
IOKitPersonalitiesis used by an I/O Kit driver for automatically loading the driver when it is needed.
There are several more kext-specific
Info.plist keys that allow you to further describe your kext. For a complete discussion of all kext
Info.plist keys, including keys that refer to kernel-specific runtime facilities, see Info.plist Properties for Kernel Extensions.
This is your kext’s compiled, executable code. Your executable is responsible for defining entry points that allow the kernel to load and unload the kext. These entry points differ depending on the Xcode template you use when creating your kext. Table 1 describes the default differences between the two kext Xcode templates. This table is intended to illustrate only the most common use of each template; the kernel does not differentiate between kexts created with different templates, and it is possible to incorporate elements of both templates into a kext.
Generic kernel extension template
IOKit driver template
C functions registered as callbacks with relevant subsystems
Subclasses of one or more I/O Kit driver classes, such as
Start and stop functions with C linkage
C++ static constructors and destructors
Must be loaded explicitly
Loaded automatically by the I/O Kit when needed
Must be unloaded explicitly
Unloaded automatically by the I/O Kit after a fixed interval when no longer needed
Some kexts don’t include an executable. These kexts (called codeless kexts) are typically used to tell I/O Kit to use an existing driver for your device. See Codeless Kernel Extensions Match New Devices to Existing Drivers for more information.
Additional Resources and Plug-ins
Kexts sometimes require additional resources, such as firmware for a device. If your kext requires a resource, put it in the
Resources folder of your kext’s bundle. If you plan to localize your resources, keep in mind that kernel-space code does not detect localized resources. User-space code does detect localized resources in
.lproj subfolders of the
Resources folder, so if your resource is accessed only by user-space code, localization is straightforward.
In addition to general resources, kexts can contain plug-ins, including other kexts. If your kext uses a plug-in, put it in the
PlugIns folder of your kext’s bundle. Make sure that plug-in kexts do not contain plug-in kexts of their own; only one level of plug-ins is detected in order to limit file system traversal during early boot.
Kernel Extensions Have Strict Security Requirements
Kexts execute in kernel space and run in supervisor mode; consequently, files and folders in a kext bundle must be owned by the
root user and the
wheel group. Files must have the permissions
0644, and folders must have the permissions
0755. A kext that fails to meet these requirements will not load into the kernel.
During development, to ensure that your kext has the proper ownership and permissions, create a copy of your kext as the root user.
% sudo cp -R MyKext.kext /tmp
This method requires creating a new copy of the kext every time you build it.
Kernel Extensions Must be Developer ID for Kexts Signed and Reside in /Library/Extensions
With System Integrity Protection, kernel extensions must be signed with a Developer ID for Signing Kexts certificate, and installed into the
You can request a Developer ID Certificate for signing kexts by visiting https://developer.apple.com/contact/kext and filling out the required details.
See Kernel Extensions in System Integrity Protection Guide for more information.
Codeless Kernel Extensions Match New Devices to Existing Drivers
A codeless kext is a kext bundle that does not contain an executable. A codeless kext’s
IOKitPersonalities dictionary names other kexts that are loaded when a personality matches on a device. Each of these other kexts must have an executable. Codeless kexts are commonly used with USB and HID devices that are driven from user space. Because the kernel driver implements a standard protocol, it can be used by nearly all devices in these categories.
For example, most USB printers share a generic driver provided by Apple,
AppleUSBMergeNub.kext. Apple cannot include the matching dictionary for every printer in this kext, so you can install a codeless kext with a personality that matches your printer and set the personality's CFBundleIdentifier to
com.apple.driver.AppleUSBMergeNub. When your printer is attached to the computer,
AppleUSBMergeNub.kext is loaded to drive it. Listing 1 shows an example of such a codeless kext’s IOKitPersonalities dictionary, in XML format.
Listing 1 The
IOKitPersonalities dictionary of a codeless kext