Skip to content

fix(udev): restore device node permissions on unhide and re-trigger udev add - #710

Open
nileshchakraborty wants to merge 2 commits into
ShadowBlip:mainfrom
nileshchakraborty:fix/unhide-restore-permissions
Open

fix(udev): restore device node permissions on unhide and re-trigger udev add#710
nileshchakraborty wants to merge 2 commits into
ShadowBlip:mainfrom
nileshchakraborty:fix/unhide-restore-permissions

Conversation

@nileshchakraborty

@nileshchakraborty nileshchakraborty commented Sep 12, 2026

Copy link
Copy Markdown

When hide_device() hides an input device, dynamic udev rules modify permissions on the source devnode.

On service stop or unhide_all(), permissions on existing device nodes were not restored, leaving them inaccessible (#686).

Changes

  • Dynamically record pre-existing device permissions before hiding and restore them on unhide_device() / unhide_all().
  • Clean up /dev/inputplumber/by-hidden symlinks on restore.
  • In reload_all(), trigger remove and add actions scoped to -s input and -s hidraw to reapply default udev tags and ownership.

Fixes #686

@nileshchakraborty
nileshchakraborty force-pushed the fix/unhide-restore-permissions branch from efe8661 to 786b14f Compare September 12, 2026 04:49
When unhiding devices or stopping inputplumber, character device nodes
that were grabbed previously had mode 000 applied directly to the node.
Udev change events do not reset filesystem permissions on existing nodes,
leaving the system without functioning pointer devices on service exit.

Explicitly restore 0660 mode permissions on unhidden nodes and trigger
udev with both remove and add actions in reload_all.

Fixes: ShadowBlip#686
@nileshchakraborty
nileshchakraborty force-pushed the fix/unhide-restore-permissions branch from 786b14f to 1063309 Compare September 12, 2026 04:53
Comment thread src/udev/mod.rs Outdated
Comment thread src/udev/mod.rs Outdated
@nileshchakraborty

Copy link
Copy Markdown
Author

Testing & Validation

  1. Unit Tests & Clippy (Fedora 44 container):

    • cargo test --all-targets -> 10 passed, 0 failed, 4 doc-tests passed.
    • cargo clippy --all-targets -- -D warnings -> Clean, 0 warnings.
  2. Live Device Reproduction & Verification (Bazzite Deck 44, ROG Ally X):

    • Confirmed hidden nodes under 0.79.0 before service stop:
      /dev/inputplumber/by-hidden/event3 -> /dev/input/event3 (mode 0000: c---------)
      /dev/inputplumber/by-hidden/event4 -> /dev/input/event4 (mode 0000: c---------)
      /dev/inputplumber/by-hidden/event6 -> /dev/input/event6 (mode 0000: c---------)
      /dev/inputplumber/by-hidden/hidraw5 -> /dev/hidraw5 (mode 0000: c---------)
      /dev/inputplumber/by-hidden/hidraw6 -> /dev/hidraw6 (mode 0000: c---------)
      /dev/inputplumber/by-hidden/js0 -> /dev/input/js0 (mode 0000: c---------)
      
    • Verified that fs::set_permissions(&target, 0o660) resets character node permissions to crw-rw---- and scoped udev triggers (udevadm trigger -s input -s hidraw) restore uaccess console ACLs upon stopping.

@nileshchakraborty nileshchakraborty changed the title fix(udev): restore 0660 mode permissions on unhidden devices and re-trigger udev add fix(udev): restore device node permissions on unhide and re-trigger udev add Sep 12, 2026
Comment thread src/udev/mod.rs
if Path::new(&hidden_symlink).exists() {
let _ = fs::remove_file(&hidden_symlink);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retain comments

Comment thread src/udev/mod.rs
}
}

// Reload udev

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too

Comment thread src/udev/mod.rs

/// Unhide all devices hidden by InputPlumber
pub async fn unhide_all() -> Result<(), Box<dyn Error>> {
// Remove all created udev rules

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too

Comment thread src/udev/mod.rs
let _ = fs::remove_dir("/dev/inputplumber/by-hidden");
}

// Move all devices back

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too

Comment thread src/udev/mod.rs
saved.clear();
}

// Reload udev rules

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stopping inputplumber.service leaves grabbed evdev nodes at mode 000 (system left without a pointer)

2 participants