Basic facts about MacOS X kernel extensions
written on Tue 21 April 2015
Here are some facts about OS X's kernel extensions (
kexts) that I've managed to aggregate.
Normally, whole directory that contains the kext must be owned by the
user. If it's not, you will get errors during loading phase of the kext.
Additionally, your kext must be writable by
root only. If it's not, you will
get loading errors!
Be aware that you need to use the
-R option when performing the
command. This means that you need to fix the privileges for all the files and
directories inside the kext bundle.
You can dynamically check for conformance to these rules by using the
tool to load your kext (you can also examine the
-tn -- test and do not load --
option). It's usage is the same as
kextload, so I assume you won't have any
When writing a new kernel extension it is often a good idea to test it on multiple systems. Fastest way for the developer to perform such tests is to use multiple virtual machines, where each machine is controlled by a different version of the operating system.
Different versions of MacOS X have different policies when it comes to loading thirdparty (i.e. your own) kernel extensions. It is sane to assume that you can't codesign each compilation of your kext, so it's important to know if a system will allow loading unsigned kexts or not.
OS X 10.8 (Mountain Lion, and earlier)
Digitally signed kexts are not allowed. Yes, they're not supported. If you digitally sign a kext file by using an embedded digital sign inside the main kext MachO binary file, the system will refuse to load your kext. So, as far as development requirements goes, you're good to go already!
OS X 10.9 (Mavericks)
Respects codesign, but not enforces it. If your kext is not digitally signed, it
still can be loaded (at least by using the
kextload utility). The system can
emit a warning with a message that it can't verify the origin of your kext, but
it will load it anyway. If you're OK with this message, you're good to go, as a
developer. But there's a small catch: if you install inside
/Library/Extensions, you need to have your kext digitally signed. If it's not
signed, it will not load.
So, in order to be protected from tampering of your kext in Mavericks, you need
to install your kext inside
OS X 10.10 (Yosemite)
Complete enforcement of codesign. Your kext will not be loaded if it's not digitally signed. As a developer, you're screwed.
If you're doing your development on a VM, you can force your system to disable checking of digital signs of every kext. Important thing to note is that it will literally disable the digital sign checking code across the whole system, so don't do it on the computers of your clients!
Disabling is easy. You need to append the
kext-dev-mode=1 option to the boot
args of your kernel, by using the
sudo nvram boot-args=kext-dev-mode=1
Please be aware that you need to append this option to your existing boot-args, not overwrite those args (who knows what's in there).
nvram doesn't work in VirtualBox. If you're using VirtualBox, try this
command on your host machine:
VBoxManage setextradata <name_of_your_vm> "VBoxInternal2/EfiBootArgs" "kext-dev-mode=1"
If you're using a Hackintosh virtual machine inside VirtualBox that doesn't use EFI (not that I'm using it), and you still can't get it to work, you can also try this one:
You can also insert this option to the
Kernel Flags entry inside this file:
Whatever will be more convinient for you.
OS X 10.11 (El Capitan)
Like Yosemite, complete enforcement of codesign. However, there is a twist: codesign policy on El Capitan is different than on Yosemite. El Capitan introduced something that is called System Integrity Protection, which seems to wrap up some things that were previously used by codesign subsystem alone.
kext-dev-mode=1 option that was previously used to disable kext digital
sign enforcement doesn't work anymore. At the time of writing this post, El
Capitan is still not fully released, so the method below can change, but it
SIP can be disabled by following these steps:
Booting into Recovery OS (hit
Security Configurationoption, which can be found inside
System Integrity Protectioncheckbox,
Hit Apply and reboot the machine.
Theoretically, it should work. The setting is still saved inside NVRAM, so i'm not sure why they didn't use the same NVRAM option as before, but they seem to had their reasons (I hope).
If, by chance, this won't work, try another method.
Utilities/Terminal, and use
csrutil command to disable
# csrutil status System Integrity Protection status: enabled. # csrutil disable Successfully disabled System Integrity Protection. Please restart the machine for changes to take effect.
However, if you're using VirtualBox, this won't work. You can't simply "enter recovery OS". Instead, you will want to enter "installation OS", or whatever the name is. Follow this article in order to find out how to do it.
Problems with codesign in Mountain Lion (10.8) and earlier OS X versions
Apple suggests that if you would want to retain backward compatibility before
Mountain Lion release (10.8), you need to install a signed kext inside
/Library/Extensions, as well as unsigned kext inside
/System/Library/Extensions. OS X versions before Mavericks (10.9) will
ignore the signed kext, and load only unsigned kext.
It appears that you can also use a different technique of codesigning of a kext
by embedding an external digital sign. To do this, examine the
codesign utility. It should place the digital sign externally inside
_CodeSignature/CodeSignature file. This works, because normally, an
internally embedded digital sign is placed inside
command, inside main kext binary. The problem is that older dynamic linkers in
older OS X versions can't handle this load command, only new ones can handle it.
By placing it outside of the kext binary, you won't confuse older linkers with
an unknown load command.