Ignore readers using PCSCLITE_IGNORE udev property

Version 2.3.2 of pcsc-lite (New version of pcsc-lite: 2.3.2) introduced a new way to ignore a smart card reader.

The patch included in pcsc-lite is from Valtteri Vuorikoski and I will quote his git commit message in this article.

Use case

"This is similar to the existing filtering support provided by PCSCLITE_FILTER_IGNORE_READER_NAMES (Remove and/or customize PC/SC reader names), but allows using the full range of udev rules to match specific devices. For example, if you have several Yubikeys and one is attached to a specific USB port that is being forwarded to a virtual machine (viz. it should not be touched by programs on the host machine), this facility allows setting a rule to keep pcscd away from that Yubikey. Yubikeys attached to other ports keep working normally."

udev

By default pcsc-lite uses libudev to detect readers events (plug or unplug of a USB reader). The idea is to use a flag set by udev to tell pcsc-lite to ignore a reader.

Example rule that targets a Yubikey attached to a specific USB port and causes pcscd to ignore that device:

ACTION!="remove|unbind", SUBSYSTEM=="usb", ATTR{idVendor}=="1050",
ATTR{idProduct}=="0406", KERNEL=="1-2.3", ENV{PCSCLITE_IGNORE}="1"

The KERNEL match targets a USB device attached to port 3 of a hub on port 2 of USB bus 1, and rule sets property PCSCLITE_IGNORE to cause the device to be ignored.

The reader with idVendor=0x1050 and idProduct=0x0406 is the YubiKey FIDO+CCID from Yubico.

Or if you want to ignore any reader connected to USB port 1-3:

ACTION!="remove|unbind", SUBSYSTEM=="usb", KERNEL=="1-3", ENV{PCSCLITE_IGNORE}="1"

You put the above rule is a file /etc/udev/rules.d/foobar.rules and voila.

Config

To know what value for KERNEL= to use you can run udevadm monitor and connect a USB reader. You will get something like:

$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[2022.067560] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
KERNEL[2022.069016] change   /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
KERNEL[2022.069332] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0 (usb)
KERNEL[2022.069416] bind     /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
UDEV  [2022.690370] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
UDEV  [2022.695881] change   /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
UDEV  [2022.700310] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0 (usb)
UDEV  [2022.728691] bind     /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)

You can see the "1-3" information to use in the .rules file.

Debug

To debug your configuration and check the new field PCSCLITE_IGNORE is correctly set you can use udevadm monitor --property and you get something like:

$ udevadm monitor --property
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[2265.405075] add      /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-3
SUBSYSTEM=usb
DEVNAME=/dev/bus/usb/001/015
DEVTYPE=usb_device
PRODUCT=8e6/3437/100
TYPE=0/0/0
BUSNUM=001
DEVNUM=015
SEQNUM=4692
MAJOR=189
MINOR=14

[...]

UDEV  [2266.066186] bind     /devices/pci0000:00/0000:00:14.0/usb1/1-3 (usb)
ACTION=bind
DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-3
SUBSYSTEM=usb
DEVNAME=/dev/bus/usb/001/015
DEVTYPE=usb_device
DRIVER=usb
PRODUCT=8e6/3437/100
TYPE=0/0/0
BUSNUM=001
DEVNUM=015
SEQNUM=4695
USEC_INITIALIZED=2265405122
ID_BUS=usb
ID_MODEL=USB_SmartCard_Reader
ID_MODEL_ENC=USB\x20SmartCard\x20Reader
ID_MODEL_ID=3437
ID_SERIAL=Gemplus_USB_SmartCard_Reader
ID_VENDOR=Gemplus
ID_VENDOR_ENC=Gemplus
ID_VENDOR_ID=08e6
ID_REVISION=0100
ID_USB_MODEL=USB_SmartCard_Reader
ID_USB_MODEL_ENC=USB\x20SmartCard\x20Reader
ID_USB_MODEL_ID=3437
ID_USB_SERIAL=Gemplus_USB_SmartCard_Reader
ID_USB_VENDOR=Gemplus
ID_USB_VENDOR_ENC=Gemplus
ID_USB_VENDOR_ID=08e6
ID_USB_REVISION=0100
ID_USB_INTERFACES=:0b0000:
ID_VENDOR_FROM_DATABASE=Gemalto (was Gemplus)
ID_MODEL_FROM_DATABASE=GemPC Twin SmartCard Reader
ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:3
ID_PATH=pci-0000:00:14.0-usb-0:3
ID_PATH_TAG=pci-0000_00_14_0-usb-0_3
ID_SMARTCARD_READER=1
ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_3
SYSTEMD_WANTS=smartcard.target
SYSTEMD_USER_WANTS=smartcard.target
PCSCLITE_IGNORE=1
MAJOR=189
MINOR=14
TAGS=:uaccess:security-device:seat:systemd:
CURRENT_TAGS=:uaccess:security-device:seat:systemd:

In pcscd logs I get:

04337722 [140613033731776] ../src/hotplug_libudev.c:656:HPEstablishUSBNotifications() USB Device add
00000411 [140613033731776] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x08E6, PID: 0x3437, path: /dev/bus/usb/001/016
00000303 [140613033731776] ../src/hotplug_libudev.c:417:HPAddDevice() Device Gemalto PC Twin Reader at /dev/bus/usb/001/016 (1-3:1.0) has PCSCLITE_IGNORE set: ignored

And I do not see the PC/SC reader with pcsc_scan command:

$ pcsc_scan -r
No reader found.

Conclusion

I am sure you will find other use cases for this new feature.

Thanks to Valtteri Vuorikoski for the patch. If you have ideas of changes or improvements for pcsc-lite do not hesitate to submit them.