Skip to content

fix(linux): install udev rules to /usr/lib and declare package runtime dependencies - #1006

Open
hikarisakamoto wants to merge 3 commits into
AprilNEA:masterfrom
hikarisakamoto:fix/linux-packaging-hygiene
Open

fix(linux): install udev rules to /usr/lib and declare package runtime dependencies#1006
hikarisakamoto wants to merge 3 commits into
AprilNEA:masterfrom
hikarisakamoto:fix/linux-packaging-hygiene

Conversation

@hikarisakamoto

Copy link
Copy Markdown

Summary

Three Linux packaging hygiene fixes. The udev rule installed to /etc/udev/rules.d, the admin directory — the vendor convention is /usr/lib/udev/rules.d, it matches what package.nix already does (and asserts), and on Arch it is what makes pacman's systemd hook (udevadm control --reload + trigger -c change + settle, fired only for usr/lib/udev/rules.d/*) re-apply device access on install/upgrade with no replug. The deb and rpm packages also declared no runtime dependencies at all, so a fresh install on a minimal system hit dlopen failures at first launch.

Changes

  • packaging/linux: udev rule destination moves to /usr/lib/udev/rules.d/70-openlogi.rules (nfpm.yaml, install.sh, uninstall.sh, the rules-file header, and the manual-install command in docs/INSTALL-linux.md). install.sh removes a pre-existing /etc copy, which would silently shadow the vendor file; uninstall.sh removes both locations.
  • packaging/linux: new deb.depends and rpm.depends, and hicolor-icon-theme added to archlinux.depends. The lists mirror what the released binaries actually load (readelf NEEDED + dlopen-string audit of the v0.8.0 assets): libwayland-egl was missing from every obvious guess, while libdbus (zbus speaks the wire protocol — dbus covers the daemon), libfontconfig (a pure-Rust parser reads fonts.conf, so deb depends on fontconfig-config, which owns that file), and libGL/GLX (wgpu resolves GL through EGL only) are never loaded and are deliberately absent. nfpm cannot emit pacman optdepends (checked through 2.47.0), so that stays AUR-territory.
  • xtask: the latest-json exclusion test and doc comment now cover .pkg.tar.zst alongside .deb/.rpm (behavior unchanged — classify() already excluded it).

Testing

  • nfpm package (2.46.3, CI's pinned version) for all three packagers against this branch: bsdtar -tf shows the rule at usr/lib/udev/rules.d/ and no etc/ entry in every format; .INSTALL still carries the udevadm script; pacman -Qip and the deb control show the new depends.
  • shellcheck + shfmt -d on install.sh/uninstall.sh; typos 1.49.0 with .config/typos.toml; udevadm verify unaffected (rules content unchanged).
  • Not run on this host (no rust ≥ 1.98 toolchain / no nix): all cargo gates including cargo test -p xtask for the test change, cargo xtask linux package (direct nfpm invocation used instead), and Nix CI (nix fmt --check / nix flake check) — the Nix CI workflow will trigger on this PR via its packaging/linux/** path filter. Not runtime-tested on hardware.
  • To verify on hardware (Arch): install the package, replug nothing, and check getfacl /dev/hidraw* shows the seat user's ACL; pacman -Ql openlogi | grep udev shows only the usr/lib path.

/etc/udev/rules.d is the admin directory: a vendor package writing there is
flagged by namcap, and an admin copy of the same name silently overrides the
packaged file. The vendor directory also matches packaging/linux/package.nix,
which already installs to $out/lib/udev/rules.d and asserts it.

On Arch this is what makes device access apply without a replug: the systemd
alpm hook (reload + trigger + settle) only watches usr/lib/udev/rules.d/*.

install.sh removes a pre-existing /etc copy so older manual installs stop
shadowing the vendor file; uninstall.sh removes both locations.
The deb and rpm packages declared no dependencies at all, so a fresh install
on a minimal system hit dlopen failures at first launch. The lists mirror
what the binaries actually load (readelf NEEDED + dlopen strings): libxcb and
libxkbcommon{,-x11} linked by the GUIs; libvulkan, libEGL, libwayland-client,
and libwayland-egl dlopened at runtime. Not listed because never loaded:
libdbus (zbus implements the wire protocol; the daemon package is the real
dependency), libfontconfig (a pure-Rust parser reads fonts.conf, so the deb
depends on fontconfig-config, which owns that file), and libGL/GLX (wgpu
resolves GL through EGL only).

The archlinux list gains hicolor-icon-theme for the icon directories the
package installs into; optdepends stays AUR-only — nfpm's archlinux packager
cannot emit it (checked through 2.47.0).
classify() already excludes .pkg.tar.zst (nothing matches .zst), but the doc
comment and the exclusion test predate the pacman package and named only
.deb/.rpm — a naming change could regress the exclusion unnoticed.
@greptile-apps

greptile-apps Bot commented Aug 25, 2026

Copy link
Copy Markdown

Greptile Summary

This PR moves Linux udev rules into the vendor directory, declares native-package runtime dependencies, and extends release-metadata coverage for Arch packages.

  • Moves packaged and manually installed udev rules from /etc to /usr/lib.
  • Adds Debian and RPM runtime dependencies plus the Arch icon-theme dependency.
  • Updates release metadata documentation and tests for .pkg.tar.zst artifacts.

Confidence Score: 3/5

This PR should not merge until the installer preserves administrator-owned udev overrides; the manual copy command should also create its destination directory.

The new migration logic can erase an administrator's device-access policy and immediately activate the permissive vendor rule, while the manual instructions can fail when the new destination directory is absent.

Files Needing Attention: packaging/linux/install.sh, packaging/linux/uninstall.sh, docs/INSTALL-linux.md, packaging/linux/udev/70-openlogi.rules

Security Review

The direct installer deletes a documented administrator udev override before reloading the vendor rule, which can restore device access that the administrator intentionally restricted.

Important Files Changed

Filename Overview
packaging/linux/install.sh Moves the rule to the vendor directory but unconditionally deletes a potentially administrator-owned access-control override.
packaging/linux/uninstall.sh Removes both rule locations, including an /etc file that may have been customized independently.
packaging/linux/nfpm.yaml Moves packaged udev rules and adds runtime dependency declarations for each native package format.
docs/INSTALL-linux.md Updates the manual destination but does not create the new directory before copying.
packaging/linux/udev/70-openlogi.rules Updates installation guidance while retaining the existing device-access rules.
xtask/src/commands/release/latest_json.rs Clarifies that Arch packages are intentionally excluded from updater metadata.
xtask/src/commands/release/latest_json/tests.rs Adds coverage confirming .pkg.tar.zst packages remain excluded.

Fix all with Greploop Fix All in Codex Fix All in Claude Code

Reviews (1): Last reviewed commit: "test(xtask): cover the pacman package in..." | Re-trigger Greptile

/etc/udev/rules.d/70-openlogi.rules
/usr/lib/udev/rules.d/70-openlogi.rules
# A leftover copy in the admin directory would shadow the vendor file.
sudo rm -f /etc/udev/rules.d/70-openlogi.rules

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Administrator udev override is deleted

If an administrator customized /etc/udev/rules.d/70-openlogi.rules to restrict device access, the installer deletes that policy and immediately reloads the permissive vendor rule, unexpectedly restoring active-seat access; the uninstaller also deletes the same administrator-owned override. How this was verified: The unconditional removal was traced through the immediate udev reload to the documented vendor rule that grants active-seat access.

Knowledge Base Used: Distribution packaging and CI

Fix in Codex Fix in Claude Code

Comment thread docs/INSTALL-linux.md

```sh
sudo cp packaging/linux/udev/70-openlogi.rules /etc/udev/rules.d/
sudo cp packaging/linux/udev/70-openlogi.rules /usr/lib/udev/rules.d/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Manual install assumes vendor directory

If /usr/lib/udev/rules.d does not already exist, this cp command fails and leaves the device-access rule uninstalled. Use a command that creates the parent directory, as install.sh already does with install -D, and update the matching instruction in the rules-file header.

Knowledge Base Used: Distribution packaging and CI

Fix in Codex Fix in Claude Code

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.

1 participant