I try to build and load a basic kernel extension on macOS 13.2 Ventura on M1 (Apple Silicon).
There is a lot of literature online on macOS kext. However, many things have changed in recent versions of macOS regarding kext and most of this literature is obsolete.
Disclaimer: I know that "system extensions" should now be used instead of kext in most cases. In my specific case, this is a test kext to learn more on the Arm64 architexture and my purpose is only to read a few CPU system registers. These registers can be read at EL1 (kernel) only. This is why a system extension is not suitable and a kext is required. BTW, I already did the same thing on Linux with a dedicated loadable kernel module. I now try to transpose this to macOS.
As a prerequisite, I disabled SIP and allowed custom kexts.
I started with the kext template in Xcode and added a few traces, either using printf()
(several articles on kexts mention a printf
function in the kernel) or os_log()
. The build is successful. I copied the kext bundle in another directory and make it owned by root.
When loading the module with sudo kmutil load -p test-kext.kext
, I get the following errors when using os_log()
. When using printf()
, I have the same messages with _printf
instead of __os_log_internal
.
Error Domain=KMErrorDomain Code=31 "Error occurred while building a collection:
1: One or more binaries has an error which prevented linking. See other errors.
2: Could not use 'test-kext' because: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
test-kext specific:
1: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
" UserInfo={NSLocalizedDescription=Error occurred while building a collection:
1: One or more binaries has an error which prevented linking. See other errors.
2: Could not use 'test-kext' because: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
test-kext specific:
1: Failed to bind '__os_log_internal' in 'test-kext' (at offset 0x0 in __DATA_CONST, __auth_got) as could not find a kext which exports this symbolFailed to bind '__os_log_default' in 'test-kext' (at offset 0x0 in __DATA_CONST, __got) as could not find a kext which exports this symbol
The Xcode build is successful. In the build log, I see that the link command for the kext uses the options -no_adhoc_codesign -kext -nostdlib -lkmodc++ -lkmod -lcc_kext
. It seems that some kernel libraries are referenced and I would expect to find the log functions.
In /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform
, I have found libkmod.a
and libkmodc++.a
but I could not find any *cc_kext*
. There is no symbol *printf*
or *os_log*
in libkmod.a
and libkmodc++.a
.
How would you log kernel messages from a kext on macOS 13 and how would you build the result?