Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

In the plug-in implementation, I plan to obtain audio data from another process i.e. CFMessagePort

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

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

I did some googlging and came to this article

Technical Q&A QA1811 https://developer.apple.com/library/mac/qa/qa1811/_index.html about adding AudioServerPlugIn_MachServices in plist but still no success.

Is there anything else I need to do to make this work (like adding entitlements, code-sign) or this is not the correct approach.? I am not sure if MesssagePort mechanism works anymore under sandbox. would XPC Services be viable?

Thank you very much for your time. Any help is greatly appreciated


update 1:

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

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

CFStringRef port_name = CFSTR("com.mycompany.audio.XPCService"); CFMessagePortRef port = CFMessagePortCreateRemote(kCFAllocatorDefault, port_name); port has return the value of 0. I tried this in a different app and it works just 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 did get a console message regarding this.

com.apple.audio.DriverHelper[1314]: The plug-in named SimpleAudioPlugIn.driver requires extending the sandbox for the mach service named com.mycompnay.audio.XPCService

anyone know why??


update 2

I noticed that when I use the debug mode with coreaudiod it does successful get the object reference of the mach service. (same thing happened when I was trying the xpc_service approach) project scheme setting

Anyone??

like image 559
Allen Avatar asked Oct 15 '15 01:10

Allen


1 Answers

I'm pretty sure I was running into the same problems in my AudioServerPlugIn. I could look up and use every Mach service I tried, except for the ones I had created. And the ones I had created worked normally from a regular process.

Eventually I read the Daemonomicon and figured out that coreaudiod (which hosts the HAL plugins) was using the global bootstrap namespace, but my service was being registered in the per-user bootstrap namespace. And since "processes using the global namespace can only see services in the global namespace" my plugin couldn't see my service.

You can use launchctl to test this by having it run the program that registers your service, but with the same bootstrap namespace as coreaudiod. You'll probably need to have rootless disabled.

# launchctl bsexec $(pgrep coreaudiod) your_service_executable

With that running, try to connect from your plugin again.

From Table 2 in the Daemonomicon, you can see that only launchd daemons use the global bootstrap namespace. That explains why coreaudiod uses it. And I think it means that your Mach service needs to be created by a launchd daemon.

To make one, create a launchd.plist for your service in /Library/LaunchDaemons. Set its owner to root:wheel and make it only writable by the owner. In it, set 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

This is what I ended up with: 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 is in that repo as well, in case that's helpful.)

I ended up having to use XPC, unfortunately, but I tried CFMessagePort first and it worked fine.

It also seems to all work fine whether the plugin is signed or not. Though, as you say, you do need the AudioServerPlugIn_MachServices key in your Info.plist.

like image 70
freshtop Avatar answered Sep 30 '22 12:09

freshtop