Don't let a usbfs claim count as a kernel driver (#6744)

The vendor-ID guess rejects any device with a driver bound, on the
reasoning that libfprint drives readers from userspace so a real one sits
there unbound. But libusb claims interfaces through a synthetic usbfs
driver, so the reader binds one for as long as fprintd holds the claim —
which is exactly while it is being enrolled or verified against.

Readers that name themselves take the product-string branch and never
reach this, so the exposure is the ones that don't: Goodix 27c6:6594
reports "Goodix USB2.0 MISC", matches on vendor ID alone, and drops out
of detection mid-authentication. The menu entry disappears and the
first-run invitation stops firing while the reader is in use.

Ignore a driver link that resolves to usbfs, and keep rejecting the real
ones — usbio-bridge, usbhid, uvcvideo — including on a device that has
both.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-08-12 14:01:58 +02:00
committed by GitHub
co-authored by Claude Opus 5
parent a9c159a1f4
commit 970ec26bb0
2 changed files with 22 additions and 2 deletions
+8 -2
View File
@@ -18,9 +18,15 @@ usb_devices_path="${OMARCHY_USB_DEVICES_PATH:-/sys/bus/usb/devices}"
# — all bind one. Only the vendor-ID guess needs this; a device that names
# itself a fingerprint reader is trusted outright.
has_kernel_driver() {
local intf
local intf driver
for intf in "$1"/*:*; do
[[ -e $intf/driver ]] && return 0
[[ -e $intf/driver ]] || continue
# usbfs is the exception: libusb claims an interface through it, so a reader
# fprintd is enrolling or verifying against binds a driver for as long as it
# holds the claim. That is userspace driving the device — what a reader is
# supposed to look like — so it must not read as a kernel driver here.
driver=$(readlink -f "$intf/driver")
[[ ${driver##*/} == "usbfs" ]] || return 0
done
return 1
}
+14
View File
@@ -87,5 +87,19 @@ write_usb_devices '27c6:1234'
bind_driver '1-0/1-0:1.0' uvcvideo
assert_rejects "a vendor guess bound to a kernel driver is rejected"
write_usb_devices '27c6:1234'
bind_driver '1-0/1-0:1.0' usbfs
assert_detects "a vendor guess claimed through usbfs is still detected"
write_usb_devices '27c6:1234'
bind_driver '1-0/1-0:1.0' usbfs
bind_driver '1-0/1-0:1.1' uvcvideo
assert_rejects "a real driver alongside a usbfs claim is still rejected"
# The product-name branch is trusted outright, whatever is bound to it.
write_usb_devices '27c6:1234:Goodix Fingerprint USB Device'
bind_driver '1-0/1-0:1.0' uvcvideo
assert_detects "a self-named reader is detected with a driver bound"
write_usb_devices '1234:5678:Generic USB Device'
assert_rejects "a machine with no matching USB devices detects nothing"