The built-in driver for the sound user interface is a sandbox that prevents data from interacting with another process

I am working on a plugin based on the coreaudio user space based on the developer.apple.com/library/mac/samplecode/AudioDriverExamples/Introduction/Intro.html example

In the implementation of the plugin, I plan to receive audio data from another process, i.e. CFMessagePort

However, I received the following error in the console while trying to create the CFMessagePortCreateLocal port ...

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

I did some googlging and came to this article

QA A QA1811 technical https://developer.apple.com/library/mac/qa/qa1811/_index.html about adding AudioServerPlugIn_MachServices to plist, but still no success.

Is there anything else I need to do to make this work (e.g. adding rights, code sign), or is this not the right approach.? I'm not sure if the MesssagePort mechanism works anymore in the sandbox. Will XPC services work?

Thanks so much for your time. Any help is appreciated


update 1:

I have to create a remote port instead of the local one in the audio plug-in. Having said that, with the AudioServerPlugIn_MachServices attribute in the plist. now there is no sandboxd [559]: ([552]) coreaudiod (552) deny mach-lookup / register message in the console.

However, in my audio hal plugin (client side) I have

CFStringRef port_name = CFSTR("com.mycompany.audio.XPCService"); CFMessagePortRef port = CFMessagePortCreateRemote(kCFAllocatorDefault, port_name); the port returns 0. I tried this in another application and it works fine.

This is my server side:

 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(); 

I received a console message about this.

com.apple.audio.DriverHelper [1314]: a plug-in named SimpleAudioPlugIn.driver requires a sandbox extension for the transfer service named com.mycompnay.audio.XPCService

Does anyone know why ???


update 2

I noticed that when I use debug mode with Coreaudiod, it successfully gets a reference to the mach service object. (the same thing happened when I tried to use the xpc_service method) setting up the project scheme

Is anyone ??

+6
source share
1 answer

I am sure I came across the same problems in my AudioServerPlugIn. I could search and use all the services that I tried, except the ones that I created. And the ones I created worked fine from the normal process.

In the end, I read Daemonomicon and realized that coreaudiod (which hosts the HAL plugins) uses the global bootstrap namespace, but my service was registered in the namespace for each boot buffer. And since "processes using the global namespace can only see services in the global namespace", my plugin could not see my service.

You can use launchctl to verify this by running a program that registers your service, but with the same bootstrap namespace as coreaudiod . You may have to disable rootless.

 # launchctl bsexec $(pgrep coreaudiod) your_service_executable 

With this launch, try connecting to the plugin again.

From table 2 in Daemonomicon, you can see that only launchd daemons use the bootstrap global namespace. This explains why coreaudiod uses it. And I think that means your Mach service should be created by launchd daemons.

To do this, create launchd.plist for your service in /Library/LaunchDaemons . Set the owner of root:wheel and make it writable by the owner. In it, install the MachServices key and add the name of your service:

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

Then register it:

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

Here is what I ended up: com.bearisdriving.BGM.XPCHelper.plist.template . Please note: without the UserName / GroupName keys, your daemon will run as root. (The code is my service and the plugin is in this repo as well, in case it is useful.)

In the end, I had to use XPC, but I tried CFMessagePort first and it worked fine.

It also seems that everything works fine, whether the plugin is signed or not. Although, as you say, you need the AudioServerPlugIn_MachServices key in your Info.plist.

+3
source

All Articles