Simple input events proxy

This package consists of two tools:

  1. input-proxy-sender
  2. input-proxy-receiver

The first one is intended to run in the VM with physical input device attached (for example USB VM).

The second one is intended to run in Dom0 (or GUI VM when implemented). It will receive the events and pass them to emulated device.

input-proxy-sender

The only option is device file path, for example /dev/input/event2. Take a look at /dev/input/by-id directory for stable named symlinks. You should use event devices, not mouse or anything else.

You need to have access to the device file, which most likely means that you need to start input-proxy-sender as root, or you need some udev rule to alter file permissions.

input-proxy-receiver

This part performs events filtering according to desired device type. The tool has options to specify allowed event types:

  • --mouse - allow events specific for mouses (EV_REL and EV_KEY with BTN_LEFT, BTN_MIDDLE, BTN_RIGHT)
  • --keyboard - allow events specific for keyboards (EV_KEY, EV_LED)
  • --tablet - allow events specific for tablets/touchscreens (EV_ABS)

Additionally you can specify how emulated device should look like:

  • --name - device name (string up to 80 chars)
  • --vendor - vendor ID
  • --product - product ID

This tool uses /dev/uinput to emulate the device, which means you need:

  1. Load uinput kernel module.
  2. Set appropriate permissions, so you'll have access to it (or start the tool as root).

Security Warning

Please carefully read this security warning before using any input proxies:

https://www.qubes-os.org/doc/usb/#security-warning-about-usb-input-devices

Packages

There are two packages available:

  1. qubes-input-proxy-sender - to be installed in VM with actual input device
  2. qubes-input-proxy - to be installed in dom0

Those packages already contains useful service files. The only thing you need to do, is to setup appropriate policy in /etc/qubes-rpc/policy/qubes.InputMouse (and maybe also qubes.InputKeyboard). Default policy deny any access.

Manual usage

You can also manually use this proxy. The simplest way to do that, is to just call qvm-run:

qvm-run -u root --pass-io --localcmd="input-proxy-receiver --mouse" usbvm "input-proxy-sender /dev/input/event2"

Alternatively you can allow USB VM to initiate the connection whenever you attach your device. For that you need to create Qubes RPC service which will start input-proxy-receiver, for example /etc/qubes-rpc/qubes.InputMouse:

input-proxy-receiver --mouse

Provide appropriate policy /etc/qubes-rpc/policy/qubes.InputMouse:

sys-usb dom0 allow

Then create systemd service in your USB VM, which will call input-proxy-sender, for example /etc/systemd/system/input-sender-mouse@.service:

[Unit]
Name=Input proxy sender
After=qubes-qrexec-agent.service

[Service]
ExecStart=/usr/bin/qrexec-client-vm dom0 qubes.InputMouse /usr/bin/input-proxy-sender /dev/input/%i

And create udev rule in your USB VM, which will automatically start the service, for example /etc/udev/rules.d/input-proxy.rules:

KERNEL=="event*", ACTION=="add", ENV{ID_INPUT_MOUSE}=="1", RUN+="/bin/systemctl --no-block start input-sender-mouse@%k.service"
KERNEL=="event*", ACTION=="remove", RUN+="/bin/systemctl --no-block stop input-sender-mouse@%k.service"