Sco*_*aun 2 memory macos iokit macos-system-extension driverkit
我正在尝试了解有关 DriverKit 和内存管理的更多信息,并且我读到了这个问题:
如何在 DriverKit 系统扩展中分配内存并将其映射到另一个进程?
我想了解如何使用IOMemoryDescriptor::CreateMapping.
我写了一个小应用程序来测试我所做的(非常简化的代码):
uint8_t * buffer = new uint8_t[256];
for (int i = 0 ; i < 256 ; i++)
buffer[i] = 0xC6;
clientData in, out;
in.nbytes = 256;
in.pbuffer = buffer;
size_t sout = sizeof(out);
IOConnectCallStructMethod(connection, selector,&in,sizeof(in),&out,&sout);
// out.pbuffer now has new values in it
Run Code Online (Sandbox Code Playgroud)
在我的 Kext 用户客户端类中,我正在做(我正在简化):
IOReturn UserClient::MyExtFunction(clientData * in, clientData * out, IOByteCount inSize, IOByteCount * outSize)
{
MyFunction(in->nBytes, in->pbuffer);//this will change the content of pbuffer
*out = *in;
}
IOReturn UserClient::MyFunction(SInt32 nBytesToRead,void* pUserBuffer,SInt32* nBytesRead)
{
PrepareBuffer(nBytesToRead,&pBuffer);
...
(call function that will fill pBuffer)
}
IOReturn UserClient::PrepareBuffer(UInt32 nBytes,void** pBuffer);
{
IOMemoryDescriptor * desc = IOMemoryDescriptor::withAddressRange((mach_vm_address_t)*pBuffer,nBytes,direction, owner task);
desc->prepare();
IOMemoryMap * map = desc->map();
*pBuffer = (void*)map->getVirtualAddress();
return kIOReturnSuccess;
}
Run Code Online (Sandbox Code Playgroud)
这是我不知道如何在 DExt 中重现的地方,我认为我真的不理解CreateMapping.
或者我以前做不到的事?
在我的驱动程序中,这是我不知道如何使用的地方CreateMapping,IOMemoryMap因此可以将该缓冲区映射到内存位置并使用不同的值进行更新。
我可以创建一个IOBufferMemoryDescriptor,但如何将它绑定到我的应用程序的缓冲区?我也不明白 的各种选项CreateMapping。
请注意,在另一个测试应用程序中我已成功使用IOConnectMapMemory64()/CopyClientMemoryForType()但我想专门了解 CreateMapping()。
(我希望没关系,我多次编辑了这个问题......对 StackOverflow 来说还是个新手)
\n\n或者我以前做不到的事?
\n
简而言之,不。
\n您正在尝试映射任意用户进程内存,客户端应用程序未使用 IOKit 显式地将其标记为可供驱动程序使用。这不符合苹果关于安全、保密和沙箱的想法,因此这种东西在 DriverKit 中是不可用的。
\n显然,kext 是万能的,所以这以前是可能的,事实上,我自己在传送驱动程序时使用了该技术,然后在将所述 kext 移植到 DriverKit 时遇到了麻烦。
\n据我所知,直接访问客户端进程内存的唯一方法是:
\nIOConnectCall\xe2\x80\xa6Method()s,以便它们作为 s 到达IOMemoryDescriptor驱动程序中。请注意,这些可以长期保留在驱动程序中,但至少对于输入结构而言,用户空间端的更新不会反映在驱动程序端,因为使用了写时复制映射。因此它们应该纯粹用于沿预期方向发送数据。IOMemoryDescriptor到其空间。IOConnectMapMemory64()CopyClientMemoryForType()这确实意味着您不能使用像您正在使用的那样的间接数据结构。您必须使用“打包”结构或持久共享缓冲区的索引。
\n我所说的“打包”结构是指包含标头结构(例如 your )的缓冲区,clientData该标头结构在连续内存中后面跟着进一步的数据(例如 your buffer),通过偏移量引用到该连续内存中。整个连续内存块可以作为输入结构传递。
我已向 Apple 提交反馈,要求提供更强大的机制来在用户客户端和 dext 之间交换数据;我不知道它是否会实施,但如果这样的设施有用,我建议您也这样做。(用例子解释你想用它做什么)我们报告的人越多,它发生的可能性就越大。(IOMemoryDescriptor::CreateSubMemoryDescriptor()是在我提出请求后添加的;我不会声称我是第一个这样做的人,也不会声称 Apple 不打算在我的建议之前添加它,但他们正在积极改进 DriverKit API。 )
问题之前的原始答案被编辑得更加具体:
\n(保留是因为它一般性地解释了如何处理外部方法的缓冲区参数,这可能对未来的读者有帮助。)
\n你的问题有点模糊,但让我看看是否可以弄清楚你在 kext 中做了什么,以及你在 dext 中做了什么:
\nIOConnectCallStructMethod(connection, selector, buffer, 256, NULL, NULL);您的应用程序中调用。这意味着buffer作为“结构输入”参数传递给外部方法。sizeof(io_struct_inband_t),所以缓冲区的内容会带内发送到内核- 换句话说,它在调用时被复制IOConnectCallStructMethod()。structureInput/structureInputSize字段传递的IOExternalMethodArguments。structureInput是内核上下文中的指针,可以直接取消引用。该指针仅在方法分派执行期间有效,并且一旦方法同步返回就无法使用。IOMemoryDescriptor. 做到这一点的一种方法确实是通过IOMemoryDescriptor::CreateMapping().structureInputDescriptor IOMemoryDescriptor,它可以直接传递到设备 I/O,也可以进行内存映射以在内核中取消引用。该内存描述符直接引用用户进程的内存。DriverKit 扩展的功能受到相当大的限制,但外部方法参数的到达方式几乎完全相同。
\nIOUserClientMethodArguments小结构通过\'字段到达structureInput,该字段指向一个OSDataobject。getBytesNoCopy()您可以通过/方法访问内容getLength()。IOMemoryDescriptor,我知道的唯一方法是IOBufferMemoryDescriptor使用IOUSBHostDevice::CreateIOBuffer()或创建一个对象IOBufferMemoryDescriptor::Create,然后将数据从OSData对象复制到缓冲区中。IOMemoryDescriptor. 您可以将其传递给 I/O 函数,或者使用以下命令将其映射到驱动程序的地址空间CreateMapping()| 归档时间: |
|
| 查看次数: |
1410 次 |
| 最近记录: |