How to write udev rules

Since the adoption of Kernel 2.6, Linux has used the udev system to handle devices such as USB connected peripherals. If you want to change the behavior when you plug something into a USB port, this section is for you. As an example, we will use a USB thumb drive but these methods should translate to any device handled by udev. As a goal for this exercise we decided to create a symlink and execute a script when a specific thumb drive was loaded. The operating system we used for this exercise is Ubuntu 9.04 Jaunty Jackalope.

Background Investigation

Before writing rules, we have to gather all the information needed to identify our device. We found the block device node that the drive was assigned to by plugging it in and checking /var/log/messages. We then pass that location (/dev/sdd1) to two commands that we run at the same time. Some distributions use the “udevinfo” command but with Ubuntu 9.04 the command has changed to “udevadm info”:

udevadm info -a -p $(udevadm info -q path -n /dev/sdd1)

The output of this is pretty meaty. We need to find the top of the chain that provides the block node which is used for mounting removable storage (in our case, /dev/sdd1). Using this KERNEL as identification will ensure that our symlink points to a mountable block device and not some part of the USB controller. We are also looking for device specific identifiers that differentiate this particular thumbdrive from all others:

In writing a udev rule, any of these characteristics can be used as conditions for the rule’s execution. That being said, only properties from one parent of the device and from the device itself can be match. Trying to match values from more than one parent in the chain will be invalid and will not work.

The Rule

Rule files are stored in the /etc/udev/rules.d/ directory. We got some advice from the README in that directory on how to name rule files:

Files should be named xx-descriptive-name.rules, the xx should be
chosen first according to the following sequence points:

< 60 most user rules; if you want to prevent an assignment being
overriden by default rules, use the := operator.

these cannot access persistent information such as that from
vol_id

< 70 rules that run helpers such as vol_id to populate the udev db

< 90 rules that run other programs (often using information in the
udev db)

>=90 rules that should run last

We plan to run a script with this rule so we gave it a name that started with a higher number than our other rules but lower than 90. We used the filename:

81-thumbdrive.rules

The first part of a udev rule is the matching keys. We will use the KERNEL entry from the very top of the chain as well as the idVendor, idProduct, and serial attributes from the device specific information. This will positively identify this particular thumb drive and ignore all others. The kernel argument uses a question mark as a wild card so that if our drive were mounted on a different node (ie: sda1, sdb1, sdc1, etc.) it could still be identified.

Now that we have the keys necessary to identify the particular hardware we’re looking for we can add assignment arguments. In our case we added two. The first creates a symlink to this device inside of the /dev/ directory. The second executes a script in our home directory:

The script can do just about anything we want it to. In this case it calls the notification workaround script passing two strings from the udev rule, a delay time, and an icon to display with the pop-up.

Order of events:

Now that everything’s in place, let’s take a look at what happens when our drive is plugged in.

-USB drive is plugged into the computer

-Udev checks the /etc/udev/rules.d/ directory and starts using the rule files in order

-Udev gets to our file: 81-thumbdrive.rules and matches the “sd?1” kernel, idVendor, idProduct, and serial number of the thumbdrive.

-If udev confirms a match on our four conditions, a symlink is created at /dev/hackaday and the /home/mike/notify-plugin.sh script is executed, passing it a message that includes the kernel information.

Here we see the symlink pointing to our block device and the pop-up notification:

Other uses:

Udev rules give you control over the hardware attached to your machine. If you are working on a USB connected project, these rules will allow you to set permissions for access, execute scripts when added or removed, and provide a persistent symlink for accessing this hardware without relying on the same node name each time the device is connected. We use a udev rule to allow avrdude to access our AVR Dragon programmer without root permission. In this case our rule sets read/write permissions for owner and group, then assigns the device to the “plugdev” group. As long as the user trying to run avrdude is a member of the plugdev group the program will be able to access the dragon. Here’s the rule:

Anyone know if there’s a way to leverage this with serial-to-USB converters (such as the PL-2303)? I have a couple old serial devices that I want to identify and handle differently, but I have 2 identical PL-2303’s so they “look” like the same device? Is there some way I could communicate with it and see what it returns to differentiate that the serial device is that is behind the USB-to-serial converter??

@Marl: and if you have an idea yourself what should happen to your not so common USB-Device (e.g. Multimeter, Datalogger, Microcontroller, Homeautomation), then you have a neat way to do this under Linux, or you wait till someone writes something for you under windows, which may never happen. You decide.

Nice idea! You can use a specific USB-Stick as a Crypto-Key or save storing device with a kind of automount triggered by this stuff. Like a encoded ignition key.
Right USB-stick and right key = more safety!

I was looking into this a couple months ago, I have a sata dock that I can just drop harddrives into, and I was hoping to make it so instead of mounting the drive it would dd /dev/zero to it, making into a hard drive nuking cradle, but I couldn’t get it to work..

Anyways, why would you want to nuke a drive automaticly! that could be dangerous if you didn’t want to kill a drive. Are you trying to have something incase the FBI break your door down looking for ilegal MP3’s!

If so i always wanted a super magnet in the doorway so all drives coming out of the room would fry :)

@Jimmy: This can be spoofed with a microcontroller such as the 18F4550 using Microchip’s mass storage firmware. Get the serial number from the thumb drive and you’re in. This seems like a far more versatile system, since you can specify a set of credentials rather than just one for recognition.

I believe there was a USB Serial Key entry system posted on hackaday awhile back.

I work at a computer store and we occasionally use harddrives for cloning or testing, so when we’re done we like to at least zero the drive once before reselling it. It’d be nice to just drop it into a cradle and walk away rather than grabbing an unused computer, putting in a DBAN boot disk, booting it up and clicking through menu options.
Nothing top secret or anything, a single pass of zeroes should at least make the data unrecoverable by amateur efforts.

Thank you hack-a-day, that was the type of article I like to read … meaty, useful, original. This is what everyone wants. Keep it up!
You know how one-upon-a-time you did articles on cpld’s and etc? …. give us some more in that vein.

Mike I had a hard time reading all of your write up because of the tears I had in my eyes because it makes me proud I kept this link on my homepage. THIS is what I am looking for, you mad skill b*st*rd you! Grats man, grats! Now I need to go get some tissues to wipe my face and blow my nose.

Excellent! I had seen information of this type years ago, but couldn’t find it when I went looking. I had wanted to setup my laptop to automatically launch gpsd & gpsdrive whenever I plugged in my GPS receiver into the USB port.

Of course, I’ve long since given up on that now that I have an iPhone, but I have no doubt this kind of info will come in handy again! Thanks very much for the research and detail you put into it.

Very powerful. How would one go about executing a script this way after the drive is mounted (done automatically)? With the above rules, it’s not yet possible to automatically copy something from the disk for instance, as it’s only being mounted in step 6 according to the order of events.

Thanks for the great article, though I’ve not yet succeeded
in getting my automatic updates done – my udev rules are
matched 13 times, and i dont know how to get it matched
only a single time.
Anyways I’ve found an cleaner workaround for the
notify-send problem, just do it like this

DISPLAY=:0 /bin/su username -c ‘notify-send Oink!’

works for me (although I’m using e-notify-send, but it has
the same issues).

I was tearing my hair out with udev. This article was very helpful. I could not get udev to write any debug into to syslog and found another way to get the debug messages was (as root):
i) /etc/init.d/udev stop
ii) udevd –debug
(this runs in the foreground and logs lots of useful stuff on connect/disconnect on rules run/rule files edited etc)
Once debugged stop this and switch it back on:
iii) /etc/init.d/udev start

This is just what I needed. I have a few USB gizmos that I want to attach, that Windows recognizes as thumb drives or serial devices, but my debian box is clueless about. Most of the udev articles I;ve read seem to written with the assumption that you already know how to write udev rules. This article answered my two main questions: how to find the info to identify the device, and how udev fits into the scheme of things.

I am writing a udev rule but it is not working,
KERNEL==”pcmSwitch”, ENV{MAJOR}==”253″, SUBSYSTEM==”char”, NAME=”linuxexplore/rahul/%k”
I am writing this rule for my custom driver of a PCM switch. But i need to create the node manually, udev rule not working for me. Is there any UDEV specific method to write a driver.

Ok, 4 YEARS after this post was made, it is still extremely helpful for anyone looking to setup rotctld and rigctld with the ham radio (amateur radio) interface hamlib for linux.
(These are used as daemons to control antenna rotators and radios via software.)