[PR #455] [MERGED] fix(input): stop Wolf virtual controllers leaking into the host desktop #480

Closed
opened 2026-10-15 13:00:53 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/games-on-whales/wolf/pull/455
Author: @JBailes
Created: 7/6/2026
Status: ✅ Merged
Merged: 8/8/2026
Merged by: @JBailes

Base: stable ← Head: fix/controller-host-input-leak


📝 Commits (4)

  • 5b96404 fix(input): isolate Wolf virtual controllers from the host desktop
  • ac068f7 feat(scripts): add wolf-input-diag.sh controller passthrough diagnostic
  • 3f86094 fix(input): address review — tighten udev glob, drop dead keyboard/mouse rule
  • 8aec13b docs(input): make 85-wolf.rules the single source of truth for udev rules

📊 Changes

5 files changed (+491 additions, -25 deletions)

View changed files

📝 85-wolf.rules (+22 -12)
📝 docs/modules/user/pages/quickstart.adoc (+12 -13)
📝 docs/modules/user/pages/troubleshooting.adoc (+43 -0)
➕ scripts/README.adoc (+40 -0)
➕ scripts/wolf-input-diag.sh (+374 -0)

📄 Description

Problem

Wolf's virtual gamepads are created via uinput/uhid inside the Wolf container but appear as real devices in the host kernel. The udev rules that are supposed to keep them off the host's active seat don't do their job, so systemd-logind grants the logged-in desktop user a uaccess ACL and the streamed controller also drives the host desktop (e.g. the DualSense touchpad moves the host mouse pointer).

Fixes #451. Also matches the reports in games-on-whales/unraid-plugin#57.

Root cause

Three compounding defects in 85-wolf.rules (and the copy in the quickstart docs):

  1. Stale device names. The rules match Wolf PS5 (virtual) pad and Wolf gamepad (virtual) motion sensors, but the pad is created as Wolf DualSense (virtual) pad (src/moonlight-server/control/input_handler.cpp:126), and the kernel's hid-playstation driver names its children … pad Touchpad and … pad Motion Sensors. None of those match, so the rules never fire for the DualSense.
  2. No rule for the DualSense touchpad child device — so it kept moving the host cursor even after a user corrected the pad name.
  3. The actual leak vector. The joypad rules set only MODE/GROUP, with no seat reassignment and no uaccess removal. A uaccess ACL overrides the group permissions, so a pad leaked to the host even when its name matched — which is why the leak reproduced across Xbox, DualSense and the Wolf UI.

Fix

  • Match every Wolf virtual device by the Wolf *virtual* name glob instead of hard-coded names — covers the gamepad, the DualSense Touchpad + Motion Sensors child devices, and the hidraw node, and won't go stale on a future rename.
  • Match both the device's own name (ATTR, for the uinput pads) and any ancestor's name (ATTRS, for the uhid DualSense children + hidraw).
  • Park the devices on the phantom seat9 and strip the uaccess ACL so no logged-in host user can read them.
  • Add a troubleshooting entry for the symptom.

85-wolf.rules is now the single source of truth

Per review feedback, the rules were duplicated between 85-wolf.rules and the quickstart docs. Rather than delete the file — downstream installers (e.g. the Unraid plugin, games-on-whales/unraid-plugin#57) want a canonical URL to pull from — the file stays and the docs now fetch it instead of restating it:

curl -fsSL https://raw.githubusercontent.com/games-on-whales/wolf/stable/85-wolf.rules \
  -o /etc/udev/rules.d/85-wolf.rules

This also fixes drift the two copies had already accumulated: the docs told users to install the rules as 85-wolf-virtual-inputs.rules, while scripts/wolf-input-diag.sh checks /etc/udev/rules.d/85-wolf.rules — so the diagnostic would report "not rule-covered" on a correctly configured host.

Also dropped the stale claim that Wolf creates virtual keyboard/mouse devices — those events go to gst-wayland-display, not uinput.

New diagnostic — scripts/wolf-input-diag.sh

Host-side, non-destructive tool to validate controller passthrough and isolation (it never grabs a device, so it can't steal input from a running game):

  • host — audits every Wolf … device on the host and flags any reachable by a non-root user or not covered by the rules (the leak in this issue).
  • discover / static — lists per-container input devices and fails if a node is shared across containers.
  • monitor / live — live checks that input reaches the container it should and no other.

It doubles as the acceptance test for the rules change.

Testing

  • Device names verified against source (input_handler.cpp) and the pinned inputtino dependency; rules and script are syntax-checked.
  • ⚠️ Needs confirmation on hardware with a physical DualSense. The exact logind/udev behaviour (whether seat9 + TAG-="uaccess" fully strips the ACL on the touchpad child device) should be confirmed on a real device. Reproduce and confirm with the bundled diagnostic:
    sudo ./scripts/wolf-input-diag.sh host   # BEFORE: LEAK lines for the pad + touchpad
    sudo cp 85-wolf.rules /etc/udev/rules.d/ && sudo udevadm control --reload-rules && sudo udevadm trigger
    # reconnect the controller, then:
    sudo ./scripts/wolf-input-diag.sh host   # AFTER: all root-only, rule-covered
    

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/games-on-whales/wolf/pull/455 **Author:** [@JBailes](https://github.com/JBailes) **Created:** 7/6/2026 **Status:** ✅ Merged **Merged:** 8/8/2026 **Merged by:** [@JBailes](https://github.com/JBailes) **Base:** `stable` ← **Head:** `fix/controller-host-input-leak` --- ### 📝 Commits (4) - [`5b96404`](https://github.com/games-on-whales/wolf/commit/5b9640448ccc948cd1a51d4885692b52e357806f) fix(input): isolate Wolf virtual controllers from the host desktop - [`ac068f7`](https://github.com/games-on-whales/wolf/commit/ac068f7596a468bea4aaa8649efd8d5a3e92e5a4) feat(scripts): add wolf-input-diag.sh controller passthrough diagnostic - [`3f86094`](https://github.com/games-on-whales/wolf/commit/3f860947e8e1bf09bb3466d105832b313b8d1489) fix(input): address review — tighten udev glob, drop dead keyboard/mouse rule - [`8aec13b`](https://github.com/games-on-whales/wolf/commit/8aec13b647b2bd57e6b2a7f60f5ba51755eb0ce7) docs(input): make 85-wolf.rules the single source of truth for udev rules ### 📊 Changes **5 files changed** (+491 additions, -25 deletions) <details> <summary>View changed files</summary> 📝 `85-wolf.rules` (+22 -12) 📝 `docs/modules/user/pages/quickstart.adoc` (+12 -13) 📝 `docs/modules/user/pages/troubleshooting.adoc` (+43 -0) ➕ `scripts/README.adoc` (+40 -0) ➕ `scripts/wolf-input-diag.sh` (+374 -0) </details> ### 📄 Description ## Problem Wolf's virtual gamepads are created via `uinput`/`uhid` inside the Wolf container but appear as **real devices in the host kernel**. The udev rules that are supposed to keep them off the host's active seat don't do their job, so `systemd-logind` grants the logged-in desktop user a `uaccess` ACL and the streamed controller **also drives the host desktop** (e.g. the DualSense touchpad moves the host mouse pointer). Fixes #451. Also matches the reports in games-on-whales/unraid-plugin#57. ## Root cause Three compounding defects in `85-wolf.rules` (and the copy in the quickstart docs): 1. **Stale device names.** The rules match `Wolf PS5 (virtual) pad` and `Wolf gamepad (virtual) motion sensors`, but the pad is created as `Wolf DualSense (virtual) pad` (`src/moonlight-server/control/input_handler.cpp:126`), and the kernel's `hid-playstation` driver names its children `… pad Touchpad` and `… pad Motion Sensors`. None of those match, so the rules never fire for the DualSense. 2. **No rule for the DualSense touchpad** child device — so it kept moving the host cursor even after a user corrected the pad name. 3. **The actual leak vector.** The joypad rules set only `MODE`/`GROUP`, with no seat reassignment and no `uaccess` removal. A `uaccess` ACL overrides the group permissions, so a pad leaked to the host **even when its name matched** — which is why the leak reproduced across Xbox, DualSense and the Wolf UI. ## Fix - Match every Wolf virtual device by the **`Wolf *virtual*` name glob** instead of hard-coded names — covers the gamepad, the DualSense `Touchpad` + `Motion Sensors` child devices, and the `hidraw` node, and won't go stale on a future rename. - Match both the device's own name (`ATTR`, for the uinput pads) and any ancestor's name (`ATTRS`, for the uhid DualSense children + hidraw). - Park the devices on the phantom **`seat9`** and **strip the `uaccess` ACL** so no logged-in host user can read them. - Add a troubleshooting entry for the symptom. ## `85-wolf.rules` is now the single source of truth Per review feedback, the rules were duplicated between `85-wolf.rules` and the quickstart docs. Rather than delete the file — downstream installers (e.g. the Unraid plugin, games-on-whales/unraid-plugin#57) want a canonical URL to pull from — the file stays and **the docs now fetch it instead of restating it**: ```bash curl -fsSL https://raw.githubusercontent.com/games-on-whales/wolf/stable/85-wolf.rules \ -o /etc/udev/rules.d/85-wolf.rules ``` This also fixes drift the two copies had already accumulated: the docs told users to install the rules as `85-wolf-virtual-inputs.rules`, while `scripts/wolf-input-diag.sh` checks `/etc/udev/rules.d/85-wolf.rules` — so the diagnostic would report "not rule-covered" on a correctly configured host. Also dropped the stale claim that Wolf creates virtual keyboard/mouse devices — those events go to [gst-wayland-display](https://github.com/games-on-whales/gst-wayland-display), not `uinput`. ## New diagnostic — `scripts/wolf-input-diag.sh` Host-side, non-destructive tool to validate controller passthrough and isolation (it never grabs a device, so it can't steal input from a running game): - `host` — audits every `Wolf …` device on the host and flags any reachable by a non-root user or not covered by the rules (the leak in this issue). - `discover` / `static` — lists per-container input devices and fails if a node is shared across containers. - `monitor` / `live` — live checks that input reaches the container it should and no other. It doubles as the acceptance test for the rules change. ## Testing - Device names verified against source (`input_handler.cpp`) and the pinned `inputtino` dependency; rules and script are syntax-checked. - ⚠️ **Needs confirmation on hardware with a physical DualSense.** The exact `logind`/`udev` behaviour (whether `seat9` + `TAG-="uaccess"` fully strips the ACL on the touchpad child device) should be confirmed on a real device. Reproduce and confirm with the bundled diagnostic: ```bash sudo ./scripts/wolf-input-diag.sh host # BEFORE: LEAK lines for the pad + touchpad sudo cp 85-wolf.rules /etc/udev/rules.d/ && sudo udevadm control --reload-rules && sudo udevadm trigger # reconnect the controller, then: sudo ./scripts/wolf-input-diag.sh host # AFTER: all root-only, rule-covered ``` --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-15 13:00:53 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/wolf#480
No description provided.