Skip to content

fix(linux): report input access as denied when the event node is unreadable - #787

Open
AalmanSadath wants to merge 2 commits into
AprilNEA:masterfrom
AalmanSadath:fix/linux-permissions-event-node
Open

fix(linux): report input access as denied when the event node is unreadable#787
AalmanSadath wants to merge 2 commits into
AprilNEA:masterfrom
AalmanSadath:fix/linux-permissions-event-node

Conversation

@AalmanSadath

@AalmanSadath AalmanSadath commented Aug 22, 2026

Copy link
Copy Markdown

Summary

Settings → Permissions checked /dev/uinput and a Logitech /dev/hidraw*, and
called both being accessible Granted. The hook also needs to read the mouse's
/dev/input/event* node, and that is not implied by the other two: logind
does not grant it on its own for a Bluetooth-direct mouse, whose node hangs off
/devices/virtual/misc/uhid and has no seat. docs/INSTALL-linux.md already
lists it as a third requirement.

So a machine carrying udev rules left by another Logitech manager reported
Granted while button remapping did nothing. HID++ rides hidraw, so the device
appeared and DPI and SmartShift worked; evdev::enumerate silently skips a node
it cannot open, so the mouse never reached the hook and nothing was logged.
Reporting that state as Granted is the one thing that page exists to prevent.

Changes

  • openlogi-permissions: new probe_logitech_event(), identifying Logitech
    by sysfs device/id/vendor the way probe_logitech_hidraw already does, and
    returning the same tri-state (Some(true) readable / Some(false) present
    but denied / None none found). classify takes it as a third input.

    A None event probe deliberately does not block Granted. Only a
    definite denial downgrades, so a machine where sysfs cannot be read is never
    reported as broken.

    It counts any Logitech event node, not only the mouse's. Telling them apart
    means decoding sysfs capability bitmasks, and uaccess is granted per node by
    the same rule, so they stand or fall together.

  • openlogi-desktop: the Denied hint named only the first two
    requirements, which would have sent users to check what was already working.
    It now names the event node and says another manager's rules often cover the
    first two but not the third.

PermissionStatus carries no serde derives and is not referenced from
openlogi-ipc, so this is not a wire change and PROTOCOL_VERSION is
untouched.

Testing

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items \
  --exclude openlogi-ui --exclude openlogi-desktop --exclude openlogi-overlay --exclude openlogi-agent
cargo check -p openlogi-permissions --target x86_64-pc-windows-gnu
cargo xtask ci   # 8 passed, 1 skipped

All on Linux with RUSTFLAGS="-D warnings". The skipped xtask ci job is
tests (macos), not reproducible on this host, so not claimed green. Both
changed files are cfg-gated to Linux; the Windows cross-check covers the gating.

Verified on hardware, Fedora 44, MX Master 3S connected Bluetooth-direct,
the case this fix is about. Its event node sits at
/sys/devices/virtual/misc/uhid/0005:046D:B034.0024/input/input98, so logind
grants no ACL on its own and the bundled rule is what makes it readable.
Revoking that ACL with setfacl leaves /dev/uinput and /dev/hidraw*
accessible, which is the exact state this fixes:

Build uinput hidraw event node Reported
before OK OK denied Granted
after OK OK denied Not granted

Both return to Granted once the ACL is restored. Four new classify cases
cover the regression and the guard against over-eager denial.

Before fix:
Before

After fix:
After

Follow-on from #529 / #530, which added the event node to the udev rules and
listed it in docs/INSTALL-linux.md as a third requirement. The permissions
probe was not updated at the time and still checked only uinput and hidraw,
so it reports Granted for a machine missing exactly the access #530 was about.

…adable

The permissions probe checked /dev/uinput and a Logitech /dev/hidraw*, and
called both being accessible Granted. The hook also needs to read the mouse's
/dev/input/event* node, and that is not implied by the other two: logind does
not grant it on its own for a Bluetooth-direct mouse, whose node hangs off
/devices/virtual/misc/uhid and has no seat.

So a machine carrying udev rules from another Logitech manager reported
Granted while button remapping did nothing. HID++ rides hidraw, so the device
appeared and DPI and SmartShift worked; evdev::enumerate silently skips a node
it cannot open, so the mouse never reached the hook and nothing was logged.
Reporting that state as Granted is the one thing the page exists to prevent.

Probe the event node too, identifying Logitech by sysfs device/id/vendor the
way the hidraw probe already does. A missing event node does not block Granted:
only a definite denial downgrades, so a machine where sysfs cannot be read is
never reported as broken.

The Denied hint named only the first two requirements, which would have sent
users to check what was already working, so it now names the event node and
says that another manager's rules often cover the first two but not the third.

Verified on Fedora 44 by revoking the ACL on the mouse's event node with
setfacl: before this change the probe and the GUI both said Granted, after it
they say Denied, and both return to Granted once the ACL is restored.
@AalmanSadath
AalmanSadath requested a review from AprilNEA as a code owner August 22, 2026 09:42
@greptile-apps

greptile-apps Bot commented Aug 22, 2026

Copy link
Copy Markdown

Greptile Summary

The PR strengthens Linux permission reporting by checking every hook-relevant Logitech event node and ensuring a denied node cannot be masked by a readable sibling.

  • Adds Logitech event-node discovery and capability-bitmap decoding.
  • Gives permission denial precedence across all matching event nodes, independent of enumeration order.
  • Extends classification and regression tests for mixed-access nodes.
  • Updates the Settings guidance to describe all three required Linux device interfaces.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains, and the previously reported readable-node masking issue is fixed by scanning all matching nodes and giving permission denial precedence.

Important Files Changed

Filename Overview
crates/openlogi-permissions/src/linux.rs The event-node probe now scans all hook-relevant Logitech mouse nodes and deterministically reports denial when any matching node is inaccessible.
crates/openlogi-permissions/src/tests.rs Tests cover event-node classification, denial precedence in both enumeration orders, transient errors, and capability-bitmap decoding.
crates/openlogi-desktop/src/windows/settings/permissions.rs Linux permission guidance now explains the event-node access required for button hooks.

Reviews (2): Last reviewed commit: "fix(linux): count only hookable mouse no..." | Re-trigger Greptile

Comment thread crates/openlogi-permissions/src/linux.rs Outdated
The event probe stopped at the first readable Logitech node, so one mouse could
mask another whose node was denied — and which node came first was only the
order readdir happened to return. Raised in review on AprilNEA#787.

Letting any denial win is not enough on its own, though. A single Logitech
device publishes several event nodes, and the non-pointer ones legitimately
carry no uaccess ACL: a G502 HERO exposes "Logitech G502 HERO Gaming Mouse
Keyboard" beside the mouse, root-owned, on a correctly configured machine.
Counting every node of a Logitech device reported Denied for exactly that, a
system where both mice work.

So filter to the nodes the hook would actually grab, applying the clicks &&
moves test its own is_hookable_mouse uses, and let one denial decide among
those. The capability bitmaps come from sysfs, whose words run most significant
first.

fold_event_access is split out so the precedence rule is testable without device
nodes, including that it does not depend on walk order.

Verified with two Logitech mice attached, an MX Master 3S over Bluetooth and a
G502 HERO over USB. With both readable the probe reports Granted, and the G502's
companion keyboard node is ignored rather than dragging it to Denied. Revoking
the ACL on the G502's mouse node alone reports Denied while the MX Master's node
stays readable — the case that previously stopped at the readable node and
reported Granted. Its bitmaps, and the MX Master's, are now test fixtures.
@AalmanSadath AalmanSadath changed the title fix(linux): report input access as denied when the event node is unre… fix(linux): report input access as denied when the event node is unreadable Aug 22, 2026
@davidbudnick davidbudnick added platform: linux Linux-specific issue type: bug Something is broken or behaves incorrectly labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform: linux Linux-specific issue type: bug Something is broken or behaves incorrectly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants