WIP
An audio qube acts as a secure handler for potentially malicious audio devices, preventing them from coming into contact with dom0 (which could otherwise be fatal to the security of the whole system). It thereby mitigates some of the security risks of using USB devices and Bluetooth devices. Nonetheless, we strongly recommend carefully reading the security warning on USB input devices devices before proceeding.
With an audio qube, many kinds of devices can be used (that previously were either unsafe or impossible to use in dom0):
In this section, we will explain how to manually set up an audio qube. A lot of alternatives configurations are also possible.
Note: By making "sys-audio" disposable, volume configuration will not be persistent.
See below, some screenshot of this configuration
In ‘audio-template’, install the required packages:
sudo dnf install -y alsa-plugins-pulseaudio alsa-utils pulseaudio-qubes pulseaudio-utils pipewire-utils qubes-audio-daemon pavucontrol xfce4-pulseaudio-plugin webrtc-audio-processing qubes-core-admin-client qubes-usb-proxy
Note: You could need to first remove the package ‘pipewire-pulseaudio’ before installing the other packages.
If you want to be able to use Bluetooth devices, you also need to install the following packages:
sudo dnf install -y blueman pulseaudio-module-bluetooth cairo-dock
And the required drivers for your Bluetooth hardware, for example, some hardware will need this package:
sudo dnf install -y linux-firmware
Then we need to passthrough the PCI devices we want to ‘sys-audio’. It needs to be configured as HVM, without memory balancing.
In dom0 execute the following command:
qubes-prefs default_audiovm sys-audio
Note: qubes that were running before the moment the audiovm has started will not have sound. See Troubleshooting section.
Now you can check that sound can be played in ‘sys-audio’ by executing the following command in ‘sys-audio’.
aplay /usr/share/sounds/alsa/Noise.wav
In the screenshot below, I passed my Bluetooth device and my audio jack device to ‘sys-audio’. The name of these devices are different on every hardware.
You can check what hardware is available using ‘pavucontrol’:
See the ‘Troubleshooting’ part if you have trouble with USB audio devices.
Nothing specific to QubesOS to configure your Bluetooth device, so the explanation will be minimal.
Add the custom service ‘audiovm’ using QubesManager for your audio qube.
Adding this service will launch at startup the following command:
qvm-start-daemon --all --watch
Finally, we need to create a policy file to allow the required communications between ‘sys-audio’ and the other qubes. In dom0, create the file ‘/etc/qubes/policy.d/50-sys-audio.policy’ with the following content:
[details="Recommended way - patching source code required"]
admin.Events * sys-audio @adminvm allow target=dom0
admin.Events +domain-stopped sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.Events +domain-shutdown sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.Events +domain-start sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.Events +connection-established sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.vm.CurrentState * sys-audio @adminvm allow target=dom0
admin.vm.CurrentState * sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.vm.List * sys-audio @adminvm allow target=dom0
admin.vm.List * sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.vm.property.Get +audiovm sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.vm.property.Get +xid sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.vm.feature.CheckWithTemplate +audio sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.vm.feature.CheckWithTemplate +audio-model sys-audio @tag:audiovm-sys-audio allow target=dom0
admin.vm.property.Get +stubdom_xid sys-audio @tag:audiovm-sys-audio allow target=dom0
You additionally need to apply this patch: https://github.com/QubesOS/qubes-core-admin-client/pull/237/files [/details]
[details="Non recommended way - Giving much more permission than theorically needed"] admin.Events * sys-audio sys-audio allow target=dom0 admin.Events * sys-audio @adminvm allow target=dom0 admin.Events * sys-audio @tag:audiovm-sys-audio allow target=dom0 admin.vm.CurrentState * sys-audio sys-audio allow target=dom0 admin.vm.CurrentState * sys-audio @adminvm allow target=dom0 admin.vm.CurrentState * sys-audio @tag:audiovm-sys-audio allow target=dom0 admin.vm.List * sys-audio sys-audio allow target=dom0 admin.vm.List * sys-audio @adminvm allow target=dom0 admin.vm.List * sys-audio @tag:audiovm-sys-audio allow target=dom0 admin.vm.property.Get +audiovm sys-audio @tag:audiovm-sys-audio allow target=dom0 admin.vm.property.Get +xid sys-audio @tag:audiovm-sys-audio allow target=dom0 admin.vm.feature.CheckWithTemplate +audio sys-audio @tag:audiovm-sys-audio allow target=dom0 admin.vm.feature.CheckWithTemplate +audio-model sys-audio @tag:audiovm-sys-audio allow target=dom0 admin.vm.property.GetAll * sys-audio sys-audio allow target=dom0 admin.vm.property.GetAll * sys-audio @tag:audiovm-sys-audio allow target=dom0 [/details]
Once this is done, you can restart your ‘sys-audio’ qube. If everything has been configured correctly, you should see the active qube configured to use ‘sys-audio’ in the ‘pavucontrol’ interface of ‘sys-audio’.
In your desktop environment, you can configure shortcuts. Turn up the volume:
qvm-run sys-audio 'amixer sset Master 2%+'
Turn down the volume:
qvm-run sys-audio 'amixer sset Master 2%-'
Toggle the audio between muted and un-muted
qvm-run sys-audio 'amixer sset Master toggle'
In ‘sys-audio’, the system needs to find all the qubes of the system (and that is configured to use ‘sys-audio’ as an audiovm) and create the communication channel to receive the audio information from those qubes. The software responsible for that can be launched manually like that:
qvm-start-daemon --all --watch
In any qube, you can find the XID of your configured audio VM with this command:
qubesdb-read -w /qubes-audio-domain-xid
In any qube, pulseaudio is responsible for trying to send the audio stream to the audiovm. It is done with a specific pulseaudio module ‘vchan-sink’. Depending on some specific configurations, you could create (or any other reason), you could want to manually configure this module to define the audiovm to try to use. This is done with the ‘domid’ parameter of the module. For example, in the file ‘/etc/pulse/qubes-default.pa’:
load-module module-vchan-sink domid=XID_OF_THE_AUDIO_QUBE
In any qube, to start pulseaudio with the ‘vchan – *’ modules, run:
start-pulseaudio-with-vchan
You can have multiple audiovm. You can configure each qubes to use a specific audiovm:
qvm-prefs QUBE_NAME audiovm
qvm-prefs QUBE_NAME audiovm MYAUDIOVM
Windows qubes don't support audiovm at the moment, and are hardwired to dom0 for audio processing.
Below, example to how to add audiovm for windows qubes.
First, you need to manually edit the xen template file in dom0 "/usr/share/qubes/templates/libvirt/xen.xml"
Above the line
{% if vm.virt_mode == 'hvm' %}
Add the following content:
{% if vm.audiovm %}
{% set audiovm_xid = vm.audiovm.xid %}
{% else %}
{% set audiovm_xid = 0 %}
{% endif %}
In the rest of the file, you will find two occurences of lines starting by "cmdline=", append the following content to this line (before the closing double-quote)
-qubes-audio:audiovm_xid={{ audiovm_xid }}
Then, you need to modify to patch "stubdom-linux-rootfs". In dom0, in your home directory, execute the following bash command:
mkdir stubroot
cp /usr/libexec/xen/boot/qemu-stubdom-linux-rootfs stubroot/qemu-stubdom-linux-rootfs.gz
cd stubroot
gunzip qemu-stubdom-linux-rootfs.gz
cpio -i -d -H newc --no-absolute-filenames < qemu-stubdom-linux-rootfs
rm qemu-stubdom-linux-rootfs
nano init
After the line starting by "audio_model=", add:
# Extract network parameters and remove them from dm_args
audio_args=$(echo "$dm_args" | sed -n '/^-qubes-audio:/p')
dm_args=$(echo "$dm_args" | sed '/^-qubes-audio:/d')
get_audio_arg() {
echo "$audio_args" | sed -n 's/^.*[:,]'$1'=\([^,]\+\).*$/\1/p'
}
And in the rest of the file, replace
module-vchan-sink domid=0
by
module-vchan-sink domid=$(get_audio_arg 'audiovm_xid')
Save and close the file. Then run:
find . -print0 | cpio --null -ov \
--format=newc | gzip -9 > ../qemu-stubdom-linux-rootfs
sudo mv ../qemu-stubdom-linux-rootfs /usr/libexec/xen/boot/
Redo the same things but for the file "stubdom-linux-full-rootfs"
Some USB audio controller cannot be passed from a USB qube to an audio qube. In those cases, the audio qube need to also be a USB qube to have direct access to the PCI USB controller. For example, this is the case for the Sennheiser GSX 1XXX.
This issue is that the vchan modules of the pulseaudio daemon running in the already started qubes are not using the correct audiovm xid (ID of the xen vm). In standard setup, restarting the pulseaudio daemon is enough. Kill the pulseaudio process and run "start-pulseaudio-with-vchan". In special configuration, you may need to manually set the "domid" parameter of the vchan modules.
It may be a power-saving issue with the sound card. In the "audio-template", create the file ‘/etc/modprobe.d/50-snd.conf’ with the following content:
options snd_hda_intel power_save=0
[details="Links"] https://github.com/QubesOS/qubes-issues/issues/8093 https://github.com/QubesOS/qubes-issues/issues/8109 https://github.com/neowutran/qubes-doc/blob/sys-audio/user/advanced-topics/audio-qubes.md https://github.com/neowutran/qubes-attachment/tree/audiovm/doc [/details]