5

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?

Thomas Ward
  • 74,764
  • BTW, I failed to transcribe a rule here (the second rule had the wrong equality symbol as a result of transcribing while being tired and having my head on a swivel to type between two different computers and screens) – Thomas Ward May 21 '15 at 23:46
  • Try setting ATTRS{authorized}=0 in your first two. Another idea would be to use RUN to run some different scripts and just make sure the idVendor and idProduct detection is working as intended. – Seth May 22 '15 at 00:02
  • @Seth no change with that, and it looks like udev is processing all the rules... adding a "RUN" command to the end that outputs to syslog means all those commands that say "Good" or "Bad" device run... :/ – Thomas Ward May 22 '15 at 01:01
  • @ThomasW. , Are you looking to block all USB devices or Just USB storage devices except that model you mention? – user.dz May 24 '15 at 09:43
  • @Sneetsher the second one, however even without the kernel and subsystem and driver arguments the system is still ignoring the "ignore_device" option regardless – Thomas Ward May 24 '15 at 11:02

2 Answers2

7

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

user.dz
  • 48,105
  • Is there a way to restrict only USB storage devices in this manner (USB mice will apparently need to work on the next systems we get to replace the aging equipment in use now). – Thomas Ward May 26 '15 at 12:15
  • 2
    Amazing and perfect, this achieves exactly what we (and I) need. Kudos to you! – Thomas Ward May 26 '15 at 13:49
  • I did a test with a USB mouse and keyboard lying around here via a VM, and was able to use those devices easily. As far as I can see this works. :) – Thomas Ward May 26 '15 at 13:52
  • @ThomasW. , User can get around this, because all it does hiding the hook in the GUI. The disk still there and it can be mounted using CLI, Disks Utility or Gparted... I will look of sysfs solution – user.dz May 26 '15 at 14:00
  • 1
    True, but we only have a small handful of power users who have administrative access anyways, and none of them are of a concern for these systems. They're basically research systems and we want to block other drives in the sense that the GUI doesn't automount it and such. – Thomas Ward May 26 '15 at 14:44
  • 1
    @ThomasW. , added sysfs rules, This way, user need root power to rebind the driver. – user.dz May 26 '15 at 15:18
2

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. :/

Thomas Ward
  • 74,764
  • 1
    Your udev rules can use what is described here http://superuser.com/a/617454/34387 instead of shell script. Or you can use it in your script either. – solsTiCe May 22 '15 at 14:39
  • 1
    @solsTiCe That's a good point. We could do either, but the longer term problem is new systems that are in the category will have more than one functional USB, at which point I need it scripted to handle any USB bus/port combo. For the current implementation the dirty solution works, but it's mostly a proof of concept first before actually whittling away at it to fix it. – Thomas Ward May 22 '15 at 15:07