Search code examples
macoslinkerkerneliokitkernel-extension

IOKit and TrustedBSD policy


How can I use the MAC policies from TrustedBSD inside an IOKit kernel extension?

I already have a working IOKit extension and I would like to add some policies to it.

For testing, I wrote two dummy extensions, one using IOKit and a generic one.
The generic extension is working flawlessly, whilst the IOKit one is generating a link error for the symbols mac_policy_register and mac_policy_unregister.

$ sudo kextutil -tn /tmp/MACPolicy.kext
kxld[com.Test.MACPolicy]: The following symbols are unresolved for this kext:
kxld[com.Test.MACPolicy]:   mac_policy_register(mac_policy_conf*, unsigned int*, void*)
kxld[com.Test.MACPolicy]:   mac_policy_unregister(unsigned int)
Link failed (error code 5).
Check library declarations for your kext with kextlibs(8).

$ sudo kextlibs -v 6 -undef-symbols /tmp/MACPolicy.kext
Kext user-space log filter changed from 0xff2 to 0xfff.
Kext kernel-space log filter changed from 0xff2 to 0xfff.
Kext library architecture set to x86_64.
Kext library architecture is x86_64 (unchanged).
For all architectures:
    com.apple.kpi.iokit = 15.4
    com.apple.kpi.libkern = 15.4

For x86_64:
    2 symbols not found in any library kext:
    __Z21mac_policy_unregisterj
    __Z19mac_policy_registerP15mac_policy_confPjPv

I already added the specified libraries to my Info.plist, as well as com.apple.kpi.dsep, com.apple.kpi.unsupported, com.apple.kpi.mach or any combination of those, with no success.

All the information I could found about this was this thread on the darwin-kernel discussion list.

I am targeting OS X 10.11 for now.


Solution

  • Notice how the missing symbols are mangled as if they were C++ functions, but the functions in questions are actually plain C functions. This means when you're calling them from C++, they're using a declaration that's missing the extern "C" linkage specifier. The MAC headers don't take into account C++, so when including them from a .cpp file, you need to wrap them in an extern "C" block explicitly, like so:

    extern "C" {
    #include <security/mac_policy.h>
    }
    

    If your #include is in a mixed C/C++ header file, you'll need to make it conditional on C++ compilation using #ifdef __cplusplus as usual.