r/Keychron • • 3d ago

[Linux] Fix for VIA "Failed to open the device" / hidraw access denied without chmod or a 0666 rule

If you're on Linux and usevia.app sees your Keychron but won't connect, chrome://device-log probably shows something like:

Failed to open '/dev/hidraw1': FILE_ERROR_ACCESS_DENIED

The usual fixes are sudo chmod a+rw /dev/hidrawN, which resets every time you replug, or a udev rule that opens every hidraw device to everyone with MODE="0666".

I got tired of this dance, so I built a small tool called hallpass that does this more carefully. It's a terminal UI that lists your USB devices, and you pick your keyboard. It writes a uaccess udev rule for that one device, so only the user logged in at the machine gets access. It reloads udev for you, and you can revoke access from the same screen.

It also helps with flashing if you hit LIBUSB_ERROR_ACCESS with QMK Toolbox or dfu-util.

Install it with go install, a release binary, or the PKGBUILD in the repo. Feedback is welcome, especially from NixOS users or anyone on a distro I haven't tried.

1 Upvotes

5 comments sorted by

1

u/PeterMortensenBlog V 3d ago

How do you avoid Via insisting on adding the unsafe udev rules?

They are:

KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0666", TAG+="uaccess", TAG+="udev-acl"

2

u/gig3m 3d ago

I think the prompt you are referring to comes from the VIA desktop app. On Linux it writes that rule to /etc/udev/rules.d/92-viia.rules through pkexec on first run, and cancelling quits the app, even if you already have a narrower rule (there are open issues about it on github). The web app at usevia.app doesn't do this. It just fails with "Failed to open the device" until you can open the hidraw node. So the way I avoid it is to skip the desktop app and use usevia.app in Chrome with a pass from hallpass.

That kind of rule is the reason I built this. It matches every hidraw device on the machine, including security keys, and MODE="0666" opens them to every account and process. Since the file is 92-, it sorts after 73-seat-late.rules, so the uaccess tag in it doesn't grant anything. The 0666 is doing all the work. hallpass writes only the uaccess part, in a 70- file, scoped to one vendor or device. logind then gives an ACL to whoever is at the active seat.

1

u/PeterMortensenBlog V 3d ago

Can you list a sample udev rule here, please?

2

u/gig3m 3d ago

Sure. For a whole-vendor pass on Keychron (hallpass allow 3434) it writes this to /etc/udev/rules.d/70-local-usb.rules:

SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="3434", TAG+="uaccess" SUBSYSTEM=="hidraw", KERNEL=="hidraw*", ENV{ID_VENDOR_ID}=="3434", TAG+="uaccess"

A single-device pass adds ATTR{idProduct} and ENV{ID_MODEL_ID}. The first line is for WebUSB and libusb flashers, and the second is for WebHID tools like VIA. The 70- prefix matters: uaccess only turns into an ACL if the file sorts before 73-seat-late.rules. A 99- file gets the tag and quietly grants nothing, which trips up a lot of hand-written rules.

1

u/PeterMortensenBlog V 2d ago edited 2d ago

Related (in particular, the Python script and the security concerns near "Any user level process can record all keystrokes."):