udev rules to allow only one vendor and model USB drive but no others

So, we're working to set up an environment here where we have a secure storage setup on our Linux laptops, such that our Linux laptops can only connect a specific USB drive: a Kingston DataTraveler 2.0. Vendor:Model code is this (from lsusb): Bus 003 Device 003: ID 0951:1665 Kingston Technology

I've been trying to get these rules to work, but on a 12.04 environment the rules aren't working. (Note I've made comments with # prepended lines, but they're not in the udev files):

# If a device is NOT a Kingston drive, ignore it.
SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}!="0951", OPTIONS+="ignore_device"

# If a device is a Kingston drive, but is NOT the model we have, ignore it.
SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}=="0951", ATTRS{idProduct}!="1665", OPTIONS+="ignore_device"

# If a device is a Kingston drive and is the model we have, then run a script
SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1665", RUN+="/lib/udev/syslog-authorized-device-connected.sh"

The issue I have is that NONE of these rules are working, and I have no idea if this is even the correct approach for this.

Thoughts?


I've faced before same problem with non effective ignore_device. I couldn't figure out why then I always go with other solutions.

  • Well, ignore_device removed with udev release 148. See release note or changelog

    If you noticed, all topics suggesting the use of it are old (~ 2009).

  • A quick alternative is to use: ENV{UDISKS_PRESENTATION_HIDE}="1" (Ubuntu 12.04). For releases (>=12.10) which include udisks2 use: ENV{UDISKS_IGNORE}="1".

    Reference: Archlinux Wiki: Udisks

The other solutions are using SYSFS. Either device/authorized (as solsTiCe mentioned), device/remove or driver/unbind. See Only use Mass Storage devices on a selected USB port - how?

Difficulty comes in how to deny all storage except only one brand/model. So the rule match condition should filter a single device node, no more no less (no child or parent devices). That's why I added KERNELS=="[1-9]*-[0-9]*"

KERNELS=="[1-9]*-[0-9]*", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}!="0951", ENV{UDISKS_PRESENTATION_HIDE}="1"
KERNELS=="[1-9]*-[0-9]*", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}=="0951", ATTRS{idProduct}!="1665", ENV{UDISKS_PRESENTATION_HIDE}="1"

Well, UDisks hides only mounting hook. These may be better using SYSFS driver unbind.

KERNELS=="[1-9]*-[0-9]*", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}!="125f", ENV{IF_STORAGE_REMOVE_ME}="1"
KERNELS=="[1-9]*-[0-9]*", SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{idVendor}=="125f", ATTRS{idProduct}!="c96a", ENV{IF_STORAGE_REMOVE_ME}="1"
ENV{IF_STORAGE_REMOVE_ME}=="1", DRIVERS=="usb-storage", DRIVER=="sd", RUN+="/bin/sh -c 'echo -n %k >/sys%p/driver/unbind'"

Reference: udev rule with few parent device attributes


NOTE: Obsoleted by Sneetsher's answer. This answer is left here for legacy reasons.

So, I sorta solved this, and it was a PAIN to do.

I reexamined the restrictions in my rules, and I changed functionality. Apparently, 12.04 doesn't honor the ignore_device option. So, I improvised and wrote an unmount script. Since there's only one functional USB port on these systems, we end up with the following, which I KNOW may break other things:

/etc/udev/rules.d/100-restrict-usb-devices.rules

# If a device is NOT a Kingston drive, ignore it.
ACTION=="add", ATTRS{idVendor}!="0951", OPTIONS+="ignore_device", RUN+="/usr/bin/logger UnauthorizedUSBConnected", RUN+="/lib/udev/unmount.sh"

# If a device is a Kingston drive, but is NOT the model we have, ignore it.
ACTION=="add", ATTRS{idVendor}=="0951", ATTRS{idProduct}!="1665", OPTIONS+="ignore_device", RUN+="/usr/bin/logger UnauthorizedUSBConnected", RUN+="/lib/udev/unmount.sh"

# If a device is a Kingston drive and is the model we have, then run a script
ACTION=="add", ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1665", RUN+="/lib/udev/syslog-authorized-device-connected.sh", RUN+="/usr/bin/logger AuthorizedUSBConnected"

/lib/udev/unmount.sh - Just a script that checks first for currently existing devices, and then checks all the other drive devices and unmounts if and only if the script runs. Since all devices would be sdb, sdc, etc. there's ways to make it work for everything.


Moral of the story: the system ignores the ignore_device option in 12.04. Gotta script everything. :/