Product QVD 4.2 Virtual Deckard
QVD Docs Team <documentation@theqvd.com>
Legal notice

Introduction

This guide is meant to explain the operation of the USBIP functionality on QVD 4.2. USBIP is currently available only on Linux systems.

1. Client functionality

1.1. Requirements

  • Kernel with USBIP support enabled.

  • usbip_host module being available and loaded.

  • qvd-client-slaveclient-usbip-aux helper tool installed with setuid permissions.

There are no special steps needed on the client side. The required support is already present in recent Linux kernel versions and should be available by default in all common Linux distributions.

1.2. Security considerations

USBIP functionality is only available to applications with root access, so a setuid helper binary, qvd-client-slaveclient-usbip-aux is provided to perform those tasks on behalf of the user.

Caution is recommended when connecting devices capable of storing data via USBIP, as this grants the remote VM complete access to the device, including the ability to change or delete any information on it.

The qvd-client-slaveclient-usbip-aux tool is installed with setuid permissions. It will automatically attempt to load the usbip_host kernel driver, and set up USB device sharing.

1.3. Settings

The client displays a list of USB devices and writes selections to the configuration file, so most of the time manual changes to the device list aren’t needed.

The device list is stored in the client.usb.share_list setting. It has the format of manufacturer:product@serial. For instance 0bda:58c2@1234 is a Realtek Semiconductor webcam with serial number 1234. Multiple entries are comma separated.

2. Server functionality

2.1. Requirements

  • Kernel with QVD USBIP patches

  • vhci_hcd module being available and loaded

  • Enabling the usage of VHCI hubs in the configuration

2.2. USBIP patches

The standard USBIP functionality present in the kernel isn’t sufficient to support sharing devices with containers. To help fix that, Qindel has developed a set of kernel patches. The kernel packages available in the QVD repositories have the required patches included.

The patches have the effect of creating multiple virtual hubs, with every container getting its own. This provides a degree of security and isolation from interference by other containers.

The patches are only necessary on the server side. The client works with the standard distro-provided kernel.

The presence of a patched kernel can be verified by looking in /sys/bus/platform/drivers/vhci_hcd. The directory should contain multiple symlinks with the names of vhci_hcd.NUMBER. Each of those will be given to a container, therefore the total number of entries puts a limit on the number of containers using USBIP simultaneously. In an unpatched kernel, only vhci_hcd.0 will be present. If the directory /sys/bus/platform/drivers/vhci_hcd is missing entirely, it means the vhci_hcd module is not loaded.

2.3. Device Monitor

When a device is connected by USBIP, it’s connected to the server host. In order to grant access to use the device to the right container, qvd-hkd monitors udev events, determines which container plugged in the device, and adjusts cgroups device permissions in order to grant it permission. It also performs the reverse operation on device removal.

2.4. AppArmor Settings

LXC uses AppArmor for container isolation. In the default configuration, AppArmor blocks access to /sys/devices/system/platform. QVD comes with a custom configuration modified to allow this access.

2.5. Security considerations

In a container-based environment there’s a single kernel running on the server, which is shared among all containers. This means that when an USB device is connected to a container by the user, the device is effectively plugged into the server itself.

QVD takes care to isolate containers from each other to the extent possible. Devices can only be used by the container they were connected into, so another container can’t obtain access to them even with root access. However, some precautions are necessary.

It is crucial to avoid any software on the VM host that automatically mounts or examines USB block devices. Such software could interfere with QVD device sharing, could cause corruption on the connected devices, and could constitute a security issue.

Connecting any USB device carries some amount of risk to the server, as it might allow a malicious user to exploit a kernel vulnerability. Devices containing file systems are of particular concern, since carefully crafted file systems could be used to attack the host’s kernel. In normal operation this is mitigated by the user not having root access, and thus being unable to mount file systems.

2.6. Installation on Ubuntu

apt-get install qvd-client-slaveclient-usbip linux-image-4.15.0+
qa4 config set key=vm.lxc.use_vhci_hubs,value=1,tenant_id=-1
echo "vhci_hcd" > /etc/modules-load.d/qvd-usbip.conf

2.7. Installation on CentOS

yum install qvd-client-slaveclient-usbip kernel-4.15.0+
qa4 config set key=vm.lxc.use_vhci_hubs,value=1,tenant_id=-1
echo "vhci_hcd" > /etc/modules-load.d/qvd-usbip.conf

3. Image support

3.1. Requirements

QVD-VMA comes with everything necessary, but some adjustments may be needed in some cases.

3.2. Device Creator

Inside a container, the environment isn’t entirely the same as in a standard Linux distribution. Normally, udev and the Linux kernel work cooperatively — the kernel creates devices in devtmpfs file systems, and udev sets permissions, creates symlinks and invokes auxiliary programs.

en a QVD container, /dev is a tmpfs file systems, rather than a devtmpfs one. This means that devices aren’t created on it automatically, so when a device is plugged in, it doesn’t automatically appear in containers, although it does do so in the host.

QVD-VMA installs a script called qvd-create-device that’s called from udev and which performs the device creation functions. In order to grant the user permission to use the newly created device, it sets an ACL on the device file. This behavior can be controlled with the createdevice.acl.enable setting. The ACL applies to users who belong to group createdevice.acl.group, sets createdevice.acl.permissions permissions.

In order for this to work correctly, the user needs to belong to the group createdevice.acl.group. This can be done by ensuring vma.user.default.groups includes it in the list.

Here’s an example configuration:

# When VMA creates an user account, add it to the qvduser group (must exist as a group in the disk image)
vma.user.default.groups=qvduser

# Enable setting ACLs
createdevice.acl.enable=1

# Add an ACL for group qvduser
createdevice.acl.group=qvduser

# Allowing members read and write access to the devices shared by USBIP
createdevice.acl.permissions=rw