I am new to Mac Os kext development.
I want to develop a device driver on macOS Mojave (10.14.2) for my device.
I created a demo to check the running process of the driver, but after actually running it, I didn't find any log about the driver.
The following is the source code. Compile with xcode.
IOKitTest.cpp
/* add your code here */
#include "IOKitTest.hpp"
#include <IOKit/IOService.h>
#include <IOKit/IOLib.h>
// 类似cocoa中 super关键字
#define super IOService
// 和头文件中的宏定义类似, 自动生成一些特定的代码
OSDefineMetaClassAndStructors(com_apple_driver_IOKitTest, IOService);
bool com_apple_driver_IOKitTest::init(OSDictionary *dict)
{
bool result = super::init(dict);
IOLog("IOKitTest : did init !! \n"); // IOlog() 生成log日志, 存在在system.log里
log = os_log_create("com.apple.driver", "XmX");
os_log(log, "xmx Tests!!");
/** 遍历OSDictionary */
OSCollectionIterator *iter = OSCollectionIterator::withCollection(dict);
if (iter)
{
OSObject *object = NULL;
while ((object = iter->getNextObject()))
{
OSSymbol *key = OSDynamicCast(OSSymbol, object);
IOLog("iRedTest : key:%s ",key->getCStringNoCopy());
OSString *value = OSDynamicCast(OSString, dict->getObject(key));
if (value != NULL)
{
IOLog("iRedTest : value:%s\n",value->getCStringNoCopy());
}
}
}
return result;
}
void com_apple_driver_IOKitTest::free(void)
{
IOLog("IOKitTest : free \n");
os_log(log, "xmx Tests!!");
super::free();
}
IOService *com_apple_driver_IOKitTest::probe(IOService *provider, SInt32 *score)
{
IOService *probe = super::probe(provider, score);
return probe;
}
bool com_apple_driver_IOKitTest::start(IOService *provider)
{
bool result = super::start(provider);
IOLog("IOKitTest : start \n");
os_log(log, "xmx Tests!!");
return result;
}
void com_apple_driver_IOKitTest::stop(IOService *provider)
{
IOLog("IOKitTest : stop \n");
os_log(log, "xmx Tests!!");
super::stop(provider);
}
IOKitTest.hpp
/* add your code here */
#include <IOKit/IOService.h>
#include <os/log.h>
#ifndef IOKitTest_hpp
#define IOKitTest_hpp
class com_apple_driver_IOKitTest : public IOService {
//一个宏定义,会自动生成该类的构造方法、析构方法和运行时
OSDeclareDefaultStructors(com_apple_driver_IOKitTest);
public:
// 该方法与cocoa中init方法和C++中构造函数类似
virtual bool init(OSDictionary *dict = 0) APPLE_KEXT_OVERRIDE;
// 该方法与cocoa中dealloc方法和c++中析构函数类似
virtual void free(void) APPLE_KEXT_OVERRIDE;
// 进行驱动匹配时调用
virtual IOService *probe(IOService *provider, SInt32 *score) APPLE_KEXT_OVERRIDE;
// 进行加载时调用
virtual bool start(IOService *provider) APPLE_KEXT_OVERRIDE;
// 进行卸载时调用
virtual void stop(IOService *provider) APPLE_KEXT_OVERRIDE;
os_log_t log;
};
#endif /* IOKitTest_hpp */
info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>KEXT</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>IOKitPersonalities</key>
<dict>
<key>IOKitTest</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.driver.IOKitTest</string>
<key>IOClass</key>
<string>com_apple_driver_IOKitTest</string>
<key>IOMatchCategory</key>
<string>com_apple_driver_IOKitTest</string>
<key>IOProbeScore</key>
<integer>10000</integer>
<key>IOProviderClass</key>
<string>IOResource</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
</dict>
</dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2022 JingCe. All rights reserved.</string>
<key>OSBundleLibraries</key>
<dict>
<key>com.apple.kpi.iokit</key>
<string>18.2.0</string>
<key>com.apple.kpi.libkern</key>
<string>18.2.0</string>
</dict>
</dict>
</plist>
After the driver is loaded kextstat shows
Does the above indicate that the driver is loaded successfully?
where to view the kernel log?
Where can I learn kext demo?
Post
Replies
Boosts
Views
Activity
I get this error when loading kext.
"Authenticating extension failed: Bad code signature."
The MacBook system status is as follows.
There are a few points to illustrate.
This kext file works fine with SIP turned off in MacBook 2018 (MacOS 10.14.6).
This kext will not be released, it will only be used for debugging within our own group.
This kext has been compiled into the arm64 version.
The SIP option has been turned off in recovery mode and the option to reduce security has been checked for kext testing.
I want to use this kext (and not distribute) if I have to use the Apple Developer program for authentication and signing and authentication. What should I do if I don't need to? Or is it not caused by certified signatures?
Hardware and software configuration
MacBook Air M2 2022 16GB,
MacOS Ventura 13.2.1
Full description
This is a DriverKit that controls PCIE FPGA devices for low-latency data exchange.
This driver has been implemented on Iokit, and now it needs to be launched on Driverkit to adapt to newer Macs.
Driverkit lacks the IOMemoryDescriptor::withAddressRange(Iokit) function to convert the app's memory of any size to a Descriptor.
Currently, we use args->structureOutputDescriptor->CreateMapping to map the Descriptor passed by the application to the kernel layer.
// App
size_t ***::xxRead(long long addr, size_t size, void * buff){
std::lock_guard<std::mutex> guard(usrLock);
kern_return_t kr;
uint64_t info[2] = {(uint64_t)addr, (uint64_t)size};
kr = IOConnectCallMethod(
connect,
kUserReadIO,
info,
2,
NULL, NULL, NULL, NULL,
buff,
&size);
return size;
}
// Driverkit
const IOUserClientMethodDispatch sMethods[kNumMethods] = {
[kUserReadIO] =
{
(IOUserClientMethodFunction) &SmiPcieUc::sUserReadIo,
.checkCompletionExists = false,
.checkScalarInputCount = 2, // Read Addr, size
.checkStructureInputSize = 0,
.checkScalarOutputCount = 0,
.checkStructureOutputSize = kIOUserClientVariableStructureSize} // Read Data
};
kern_return_t SmiPcieUc::sUserReadIo (OSObject * target, void* reference, IOUserClientMethodArguments* args){
IOMemoryMap * memMap = nullptr;
uint32_t * buffKptr = nullptr;
kern_return_t rt = 0;
if(target == nullptr){
Log("***Err***: sUserReadIo Target is Null!");
return kIOReturnError;
}
if(args->structureOutputDescriptor){
rt = args->structureOutputDescriptor->CreateMapping(0,0,0,0,0, &memMap);
if(rt == kIOReturnSuccess){
buffKptr = reinterpret_cast<uint32_t *>(memMap->GetAddress());
}
else {
Log("***Err***: sUserReadIo Mapping Failed!");
return kIOReturnNoMemory;
}
} else {
buffKptr = (uint32_t *) args->structureOutput;
}
rt = ((SmiPcieUc *)target)->UserReadIo((uint64_t *)&args->scalarInput[0], (size_t *)&args->scalarInput[1], buffKptr);
OSSafeReleaseNULL(memMap);
return rt;
}
phenomenon
When StructureOutputSize is greater than 4096, args>structureOutputDescriptor exists, and when it is less than or equal to 4096, args->structureOutputDescriptor and args->structureOutput are both equal to nullptr, (in IOkit, args->structureOutput is not empty)。
How to properly convert any size of application memory into the kernel space of Driverkit?