Skip to content

Commit

Permalink
feat: allow disp-sys-usb to be an AudioVM
Browse files Browse the repository at this point in the history
- End qrexec policy with deny rules;
- Move the USB setup from sys-audio to sys-usb; and
- Document the pros and cons of the different types of USB devices
  assignment to client qubes or to the server.
  • Loading branch information
ben-grande committed Feb 28, 2024
1 parent a1b10c0 commit 047325c
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 48 deletions.
41 changes: 19 additions & 22 deletions salt/sys-audio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ Audio operations in Qubes OS.
* [Installation](#installation)
* [Usage](#usage)
* [Audio control](#audio-control)
* [Client switched it's AudioVM](#client-switched-its-audiovm)
* [Client started before it's AudioVM](#client-started-before-its-audiovm)
* [Client turned off with a device attached](#client-turned-off-with-a-device-attached)
* [How to use devices](#how-to-use-devices)
* [How to use USB devices](#how-to-use-usb-devices)
* [How to use Bluetooth](#how-to-use-bluetooth)
* [How to make the Bluetooth icon appear in the system tray](#how-to-make-the-bluetooth-icon-appear-in-the-system-tray)
* [How to attach the Bluetooth controller to the AudioVM persistenly](#how-to-attach-the-bluetooth-controller-to-the-audiovm-persistenly)
* [How to attach the Bluetooth controller to the AudioVM persistently](#how-to-attach-the-bluetooth-controller-to-the-audiovm-persistently)

## Description

Expand Down Expand Up @@ -49,18 +50,23 @@ sudo qubesctl --skip-dom0 --targets=tpl-sys-audio state.apply sys-audio.install-

### Audio control

The qube `disp-sys-audio` will be used for audio capabilities for speakers and
microphone, with builtin modules, Jack port or Bluetooth. You are be able to
control the volume via the volume icon that appears on the system tray.
The qube `disp-sys-audio` will be used for audio capabilities for speakers
and microphone, with builtin modules, Jack port or Bluetooth. You are be able
to control the volume via the volume icon that appears on the system tray.

The basics are very simple to use:
Audio control basics:

- Left click toggles the volume; and
- Scrolling the mouse from left to right changes the volume;

For more advanced features, right click the icon and click on `Open Mixer` or
`Prefences`. For greater control, use the command `amixer`.

### Client switched it's AudioVM

If the client has already started when you decided to switch the AudioVM, you
will need to restart the client qube until [upstream issue is fixed](https://github.com/QubesOS/qubes-issues/issues/8975).

### Client started before it's AudioVM

Audio will not automatically connect if the AudioVM starts after the client.
Expand All @@ -75,22 +81,13 @@ If you shutdown a client qube with a device attached, such as a microphone or
speaker, normal operation to attach the device to the same or any other qube
will fail. To be able to use the device again:

- Restart the audio server `disp-sys-audio`;
- Restart the AudioVM `disp-sys-audio`;
- Restart the audio client; and
- Attach the device to the audio client;

### How to use devices

Bluetooth and Camera are normally integrated in laptops, but they still are
USB devices internally. They will be held by `(disp-)sys-usb` or
`(disp-)sys-net`, else `dom0`.

Built-in microphones on the other hand, are directly attached to `dom0`.
- Attach the device to the audio client.

To use these devices, you have to attach them to their respective qubes:
### How to use USB devices

- audio server: Bluetooth; and
- audio client: cameras, speakers, microphones.
Please refer to the [sys-usb formula instructions](../sys-usb/README.md).

### How to use Bluetooth

Expand All @@ -102,13 +99,13 @@ system tray is to attach the Bluetooth controller persistently to the AudioVM.
If you don't do this, you will have to attach the Bluetooth controller
manually to `disp-sys-audio` after it has started and also run `blueman-tray`.

#### How to attach the Bluetooth controller to the AudioVM persistenly
#### How to attach the Bluetooth controller to the AudioVM persistently

If using Bluetooth, you probably want to have it persistently attached to the
AudioVM. Bluetooth devices are held by the USB stack, thus you need to attach
from you `(disp-)sys-usb` to the `disp-sys-audio`.
from your `(disp-)sys-usb` to the `disp-sys-audio`.

Note that if you attach the device, the AudioVM will
Note that if you attach the device persistently, the AudioVM will
[not be able to start](https://github.com/QubesOS/qubes-issues/issues/8877)
without first starting the backend holding the USB stack. You can move the
controller from the USB qube to the Audio qube, but this would decrease your
Expand Down
59 changes: 37 additions & 22 deletions salt/sys-audio/files/admin/policy/default.policy
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,48 @@

## Do not modify this file, create a new policy with with a lower number in the
## file name instead. For example `30-user.policy`.
{% set audiovm = 'disp-' ~ sls_path %}
## Literal name 'sys-usb' in case user has not installed via our formula.
admin.vm.device.usb.Available * @tag:audiovm sys-usb allow target=dom0
admin.vm.device.usb.Available * @tag:audiovm @tag:usbvm allow target=dom0
admin.vm.device.usb.Available * @tag:audiovm @anyvm deny

## Literal name 'sys-usb' in case user has not installed from our formula.
admin.vm.device.usb.Available * disp-{{ sls_path }} sys-usb allow target=dom0
admin.vm.device.usb.Available * disp-{{ sls_path }} @tag:usbvm allow target=dom0
admin.vm.device.mic.Available * disp-{{ sls_path }} @adminvm allow target=dom0
admin.vm.device.mic.Available * @tag:audiovm @adminvm allow target=dom0
admin.vm.device.mic.Available * @anyvm @anyvm deny

admin.Events * disp-{{ sls_path }} disp-{{ sls_path }} allow target=dom0
admin.Events * disp-{{ sls_path }} @adminvm allow target=dom0
admin.Events * disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.Events * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.Events * @tag:audiovm @adminvm allow target=dom0
admin.Events * @tag:audiovm @anyvm deny

admin.vm.CurrentState * disp-{{ sls_path }} disp-{{ sls_path }} allow target=dom0
admin.vm.CurrentState * disp-{{ sls_path }} @adminvm allow target=dom0
admin.vm.CurrentState * disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.CurrentState * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.CurrentState * @tag:audiovm @adminvm allow target=dom0
admin.vm.CurrentState * @tag:audiovm @anyvm deny

admin.vm.List * disp-{{ sls_path }} disp-{{ sls_path }} allow target=dom0
admin.vm.List * disp-{{ sls_path }} @adminvm allow target=dom0
admin.vm.List * disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.List * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.List * @tag:audiovm @adminvm allow target=dom0
admin.vm.List * @tag:audiovm @anyvm deny

admin.vm.property.Get +audiovm disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.property.Get +xid disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.property.Get +stubdom_xid disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.property.Get +audiovm {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.Get +audiovm @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +audio disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio-model disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.feature.CheckWithTemplate +supported-service.pipewire disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio-low-latency disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.property.Get +stubdom_xid {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.Get +stubdom_xid @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.property.GetAll * disp-{{ sls_path }} disp-{{ sls_path }} allow target=dom0
admin.vm.property.GetAll * disp-{{ sls_path }} @tag:audiovm-disp-{{ sls_path }} allow target=dom0
admin.vm.property.Get +xid {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.Get +xid @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +audio {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +audio-low-latency {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio-low-latency @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +audio-model {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio-model @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +supported-service.pipewire {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +supported-service.pipewire @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.property.GetAll * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.GetAll * @anyvm @tag:audiovm-{{ audiovm }} deny
## vim:ft=qrexecpolicy
64 changes: 60 additions & 4 deletions salt/sys-usb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ PCI handler of USB devices in Qubes OS.

* [Description](#description)
* [Installation](#installation)
* [Keyboard installation](#keyboard-installation)
* [AudioVM installation](#audiovm-installation)
* [Client installation](#client-installation)
* [Client USB proxy installation](#client-usb-proxy-installation)
* [Client cryptsetup installation](#client-cryptsetup-installation)
* [Client CTAP installation](#client-ctap-installation)
* [Access control](#access-control)
* [Usage](#usage)
* [How to use audio devices](#how-to-use-audio-devices)
* [Credits](#credits)

## Description
Expand All @@ -32,22 +39,46 @@ sudo qubesctl --skip-dom0 --targets=tpl-sys-usb state.apply sys-usb.install
```
<!-- pkg:end:post-install -->

### Keyboard installation

If you use an USB keyboard, also run:
```sh
sudo qubesctl state.apply sys-usb.keyboard
```

### AudioVM installation

If you plan to use `disp-sys-usb` as an AudioVM:
```sh
sudo qubesctl --skip-dom0 --targets=tpl-sys-usb state.apply sys-audio.install
sudo qubesctl --skip-dom0 --targets=dvm-sys-usb state.apply sys-audio.configure-dvm
qvm-tags disp-sys-usb add audiovm
qvm-features disp-sys-usb service.audiovm 1
```
And set the qube preference `audiovm` to `disp-sys-usb`:
```sh
qvm-prefs QUBE audiovm disp-sys-usb
```

### Client installation

#### Client USB proxy installation

Install the proxy on the client template:
```sh
sudo qubesctl --skip-dom0 --targets=tpl-QUBE state.apply sys-usb.install-client-proxy
```

#### Client cryptsetup installation

If the client requires decrypting a device, install on the client template:
```sh
sudo qubesctl --skip-dom0 --targets=tpl-QUBE state.apply sys-usb.install-client-cryptsetup
```

If the client requires a FIDO device, install on the client template:
#### Client CTAP installation

If the client requires a CTAP device, install on the client template:
```sh
sudo qubesctl --skip-dom0 --targets=tpl-QUBE state.apply sys-usb.install-client-fido
```
Expand All @@ -70,9 +101,34 @@ Depending on you system, one or more USB qubes will be created to hold the
different controllers. The qube names are `disp-sys-usb`, `disp-sys-usb-left`,
`disp-sys-usb-dock`.

Start a USB qube an connect a device to it. USB PCI devices will appear on
the system tray icon `qui-devices`. From there, assign it to the intended
qube.
Start a USB qube an connect a device to it. USB PCI devices will appear on the
system tray icon `qui-devices`. From there, assign it to the intended qube.

### How to use audio devices

Bluetooth and Camera are normally integrated in laptops, but they still are
USB devices internally. They will be held by `(disp-)sys-usb` or
`(disp-)sys-net`, else `dom0`.

Built-in microphones on the other hand, are directly attached to `dom0`.

To use these devices, there are two options:

1. Attaching the device (USB passthrough) to the audio client:
- Advantages:
- Easier setup as it doesn't require an AudioVM.
- Disadvantages:
- Increased latency;
- Only one qube can use the device; and
- Less secure as it exposes the Audio stack to the client.

2. Leaving devices to the AudioVM (`(disp-)sys-usb` as AudioVM):
- Advantages:
- More secure as the devices are not on the client;
- Less latency; and
- All audio clients will have the same audio capabilities.
- Disadvantages:
- Some applications might not work due to not finding the device.

## Credits

Expand Down
52 changes: 52 additions & 0 deletions salt/sys-usb/files/admin/policy/default.policy
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

## Do not modify this file, create a new policy with with a lower number in the
## file name instead. For example `30-user.policy`.

# Input {{{
{% if salt['pillar.get']('qvm:sys-usb:mouse-action', 'ask') == 'ask' -%}
{% set mouse_action = 'ask default_target=dom0' -%}
{% elif salt['pillar.get']('qvm:sys-usb:mouse-action', 'ask') == 'allow' -%}
Expand Down Expand Up @@ -36,7 +38,9 @@ qubes.InputKeyboard * @tag:usbvm @adminvm deny

qubes.InputTablet * @tag:usbvm @adminvm {{ tablet_action }}
qubes.InputTablet * @tag:usbvm @adminvm deny
# }}}

# CTAP {{{
ctap.ClientPin * @anyvm @tag:usbvm ask user=root default_target=disp-{{ sls_path }}
ctap.ClientPin * @anyvm @default ask user=root default_target=disp-{{ sls_path }}
ctap.ClientPin * @anyvm @anyvm deny
Expand All @@ -55,4 +59,52 @@ u2f.Register * @anyvm @anyvm deny

policy.RegisterArgument +u2f.Authenticate @tag:usbvm @anyvm allow target=dom0
policy.RegisterArgument +u2f.Authenticate @anyvm @anyvm deny
# }}}

# Audio {{{
{# Keep in sync with sys-audio policy #}
{% set audiovm = 'disp-' ~ sls_path %}
admin.vm.device.usb.Available * @tag:audiovm @tag:usbvm allow target=dom0
admin.vm.device.usb.Available * @tag:audiovm @anyvm deny

admin.vm.device.mic.Available * @tag:audiovm @adminvm allow target=dom0
admin.vm.device.mic.Available * @anyvm @anyvm deny

admin.Events * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.Events * @tag:audiovm @adminvm allow target=dom0
admin.Events * @tag:audiovm @anyvm deny

admin.vm.CurrentState * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.CurrentState * @tag:audiovm @adminvm allow target=dom0
admin.vm.CurrentState * @tag:audiovm @anyvm deny

admin.vm.List * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.List * @tag:audiovm @adminvm allow target=dom0
admin.vm.List * @tag:audiovm @anyvm deny

admin.vm.property.Get +audiovm {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.Get +audiovm @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.property.Get +stubdom_xid {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.Get +stubdom_xid @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.property.Get +xid {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.Get +xid @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +audio {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +audio-low-latency {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio-low-latency @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +audio-model {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +audio-model @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.feature.CheckWithTemplate +supported-service.pipewire {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.feature.CheckWithTemplate +supported-service.pipewire @anyvm @tag:audiovm-{{ audiovm }} deny

admin.vm.property.GetAll * {{ audiovm }} @tag:audiovm-{{ audiovm }} allow target=dom0
admin.vm.property.GetAll * @anyvm @tag:audiovm-{{ audiovm }} deny
# }}}

# vim:ft=qrexecpolicy

0 comments on commit 047325c

Please sign in to comment.