核心音频用户-space 插件驱动程序 - 沙箱阻止来自另一个进程的数据交互

core audio user-space plug-in driver - sandbox preventing data interaction from another process

我正在开发一个基于示例的 coreaudio 用户-space hal 插件 developer.apple.com/library/mac/samplecode/AudioDriverExamples/Introduction/Intro.html

在插件实现中,我打算从另一个进程获取音频数据,即CFMessagePort

但是,我在尝试创建端口 CFMessagePortCreateLocal 的控制台中遇到以下错误...

sandboxd[251]: ([2597]) coreaudiod(2597) 拒绝 mach-register com.mycompnay.audio

我做了一些谷歌搜索并来到这篇文章

技术问答QA1811 https://developer.apple.com/library/mac/qa/qa1811/_index.html 关于在 plist 中添加 AudioServerPlugIn_MachServices 但仍然没有成功。

我还需要做些什么来完成这项工作吗(比如添加权利、代码签名)或者这不是正确的方法。? 我不确定 MesssagePort 机制是否在沙箱下有效。 XPC 服务可行吗?

非常感谢您抽出宝贵时间。非常感谢任何帮助


更新 1:

我应该在音频插件中创建远程端口而不是本地端口。话虽如此,在 plist 中使用 AudioServerPlugIn_MachServices 属性。现在控制台中没有 sandboxd[559]: ([552]) coreaudiod(552) deny mach-lookup / register 消息。

但是,在我的音频 hal 插件(客户端)中我有

CFStringRef port_name = CFSTR("com.mycompany.audio.XPCService"); CFMessagePortRef port = CFMessagePortCreateRemote(kCFAllocatorDefault, port_name); 端口的 return 值为 0。我在不同的应用程序中尝试过,它工作得很好。

这是我的服务器端:

CFStringRef port_name = CFSTR("com.mycompany.audio.XPCService");
CFMessagePortRef  port = CFMessagePortCreateLocal(kCFAllocatorDefault, port_name, &callback, NULL, NULL);
CFRunLoopSourceRef runLoopSource =
CFMessagePortCreateRunLoopSource(nil, port, 0);

CFRunLoopAddSource(CFRunLoopGetCurrent(),
                   runLoopSource,
                   kCFRunLoopCommonModes);
CFRunLoopRun();

我确实收到了有关此的控制台消息。

com.apple.audio.DriverHelper[1314]:名为SimpleAudioPlugIn.driver的插件需要为名为com.mycompnay.audio.XPCService的mach服务扩展沙箱

有人知道为什么吗?


更新 2

我注意到,当我将调试模式与 coreaudiod 一起使用时,它确实成功地获取了 mach 服务的对象引用。 (当我尝试 xpc_service 方法时发生了同样的事情) project scheme setting

有人吗??

我很确定我 运行在我的 AudioServerPlugIn 中遇到了同样的问题。我可以查找并使用我尝试过的每一个 Mach 服务,除了我自己创建的服务。我创建的那些在常规过程中正常工作。

最后我读了 the Daemonomicon 并发现 coreaudiod(托管 HAL 插件)正在使用全局 bootstrap 命名空间,但我的服务是在 per-用户 bootstrap 命名空间。因为 "processes using the global namespace can only see services in the global namespace" 我的插件看不到我的服务。

您可以使用 launchctl 来测试它,方法是让它 运行 注册您的服务的程序,但使用与 coreaudiod 相同的 bootstrap 命名空间。您可能需要禁用 rootless。

# launchctl bsexec $(pgrep coreaudiod) your_service_executable

有了那个 运行ning,再次尝试从您的插件连接。

从Daemonomicon 中的Table 2,您可以看到只有launchd 守护进程使用全局bootstrap 命名空间。这就解释了为什么 coreaudiod 使用它。而且我认为这意味着您的 Mach 服务需要由 launchd 守护进程创建。

要创建一个,请在 /Library/LaunchDaemons 中为您的服务创建一个 launchd.plist。将其所有者设置为 root:wheel 并使其只能由所有者写入。在其中,设置 MachServices 键并添加您的服务名称:

<key>MachServices</key>
<dict>
    <key>com.mycompany.audio.XPCService</key>
    <true/>
</dict>

然后注册:

# launchctl bootstrap system /Library/LaunchDaemons/com.mycompany.audio.XPCService.plist

这就是我最终得到的结果:com.bearisdriving.BGM.XPCHelper.plist.template. Note that without the UserName/GroupName keys your daemon will run as root. (The code for my service and plugin 也在该回购协议中,以防有帮助。)

不幸的是,我最终不得不使用 XPC,但我首先尝试了 CFMessagePort,它运行良好。

无论插件是否签名,似乎都可以正常工作。虽然,正如您所说,您确实需要 Info.plist.

中的 AudioServerPlugIn_MachServices