My application “noisetorch” needs to load pulseaudio modules into pulseaudio to setup a virtual denoised microphone using xiph.org / mozilla’s rnnoise Library. Similar to NVIDIA’s RTX Voice, but for linux, and open source.
As @jamesh said the pulseaudio commands PA_COMMAND_LOAD_MODULE and PA_COMMAND_UNLOAD_MODULE are not allowed in strict confinement, as they essentially allow you to dlopen() a shared object outside of the sandbox.
My application however has no way around this, as I need to load/unload a LADSPA plugin, and other pulseaudio modules (loopback, null-sink and remap-source), to make the virtual microphone available to all other applications (e.g. Discord, Mumble, Skype, Browsers for WebRTC websites etc.)
The application has not been “officially” released yet, as I would like to provide sane install options from the get-go. But you can already find and build the source-code here: https://github.com/lawl/NoiseTorch
@pedronis - this is a new use case for classic. In essence, this application cannot use audio-playback, audio-record or pulseaudio interfaces on systems with a patched mediating pulseaudio since those systems disallow module loading since that allows sandbox escape. Today, the snap must be classic. Going forward, we could create a pulseaudio-control interface to allow this access (and/or access to pacmd), but as the accesses would allow confinement escape, it is unclear if we should pursue this (if we did, we would have to vet the publisher to the same degree as classic snaps; the escape would in practice be limited to the user’s session though (which is better than granting classic); furthermore the module loading is not terribly different from certain attacks that the (transitional) x11 interface already allows (but we’re trying to move away from transitional interfaces)). Can you comment?
Just a quick note here and this might not have been what you were saying, but only having access to pacmd would be quite cumbersome, I’d much prefer getting nice structs directly from PulseAudio, rather than having to shell out to pacmd and parse its output.
The idea would be if a snap plugged pulseaudio-control, then pulseaudio could check for that and allow/disallow module loading, etc (it could additionally allow access to the cli socket). Whether we want to do that or not is the discussion point with @pedronis.
Having a pulseaudio-control, possibly even carrying an allowlist of modules that can be loaded would be the best approach, I don’t know what the effort and timelines would be for that though.
Update: NoiseTorch now also needs to either elevate to root or CAP_SYS_RESOURCE. This is necessary because it temporarily needs to lift the max realtime timeout rlimit (RLIMIT_RTTIME) on pulseaudio.
The reason is that pulseaudio dlopen()'s the shared object when already under real-time contraints, this leads to the Kernel SIGKILLing pulseaudio for some users. I do not see another way to solve this other than temporarily removing the rlimit on Pulse, which is currently done by spawning a separate process with pkexec.
According to this thread this is currently unsupported, which, if so means this request can be removed, as a snap package is not possible in that case.
@lawl - the discussion in that thread concerns strict mode snaps - in this case, if noisetorch were granted use of classic confinement then this would not be an issue.
@pedronis - as @jdstrand commented above, since there is no pulseaudio-control interface at the moment, the only option for now would be classic confinement for this type of snap. However, this does not fit in any of the current categories that we would normally grant classic confinement for. As such, should we add a new category for the moment for this type of snap to allow classic confinement?
Note that the process-control interface allows CAP_SYS_RESOURCE and could probably be made to work. As for pkexec, you are right that this is not currently supported in strict mode, but it could be at a future date. An alternative approach would be extending userd to run pkexec on behalf of your snap. Both needs design and aren’t currently roadmapped. Today, use of pkexec is an unsupported use case for classic.
That said, the need for your snap to adjust RLIMIT_RTTIME suggests there is a bug in pulseaudio and perhaps you should try to get it fixed there. Barring that, once pulseaudio-control is implemented and your snap could otherwise be made strict, I think the path forward would be instead of using pkexec or the process-control interface, for you to use the system-files interface to read /etc/pulse/daemon.conf so you could alert users to make any necessary changes if they’ve set . Alternatively, you could use it for write access to the file so your snap could make the change itself (which could be done in a configure hook or one-shot daemon).
@alexmurray - you’re right that this doesn’t fit any currently supported use cases, but there is a clear path forward with a pulseaudio-control interface and it should be noted that on systems without a mediating pulseaudio (ie, non-Ubuntu and its derivatives currently), this snap should be able to work today in strict mode. As such, I think we don’t need to worry about adding a new use case to our processes at this time; we just need someone to create the pulseaudio-control interface and adjust the Ubuntu patches to check for it. This would likely fall on the desktop team (cc @kenvandine and @jamesh, but it doesn’t have to).
At this point per @pedronis comments (and our agreement that is the path forward), the requirements are understood but I’d like to put a condition on use of classic: @lawl, once the pulseaudio-control interface is implemented and the pulseaudio mediation patches updated, will you move your snap from classic to strict mode? Also, other than potentially writing a configure hook/one-shot daemon for modifying daemon.conf, will your snap ship any services?
Not a bug. You could call it a design flaw. They are allowing loading ladspa modules at runtime, which is something i need to do. But that causes a dlopen() in pulse which is running as a realtime process. dlopen() in realtime code is a bad idea, but nothing the pa devs can just fix without redesigning completely how modules work.
so you could alert users to make any necessary changes if they’ve set
No, thats a bad idea. The limit is there for a reason and i’m not going to tell people to just remove it. We (automatically) remove it exactly for the short duration where it causes an issue and then immediately reinstate it.
NoiseTorch does not currently touch any system service files and I have no current plans or requirements for that. The same goes for shipping services myself.
If pulse-control and process-control allow me to do what’s necessary, i’ll happily move over once possible. As you said process-control gives CAP_SYS_RESOURCE there should (currently) be no need for pkexec as long as it can see the pulseaudio process outside the sandbox and temporaily lift it’s RLIMIT_RTTIME
Edit: Sorry one last thing process-control sais Auto-connect: no. I would like for my application to work out of the box though, so as far as i understand, i would need to request an auto-connect for this? If so, then that’s also something i would require once confined.
Edit 2: There is no hurry until this bug is resolved, so you can move this down the priority queue if necessary.
As per @jdstrand’s comment above, the requirements for classic confinement as a temporary measure until pulseaudio-control is available are understood. @advocacy, can you please perform publisher vetting?