Udev rules

Udev rules are the new way to control how devices are handled on Linux systems. Using the udev rules presented below, a “magic USB hub” can be created that automatically mounts any block device connected downstream from the hub as read-only.

Linux systems ship with a set of standard udev rules. Administrators may customize their systems by adding their own rules to the /etc/udev/rules.d directory. Like many system scripts (i.e. startup scripts), the order in which these rules are executed is determined by the filename. Standard practice is to start the filename with a number which determines when it is loaded.

When the rules in the rules file below are run, all of the information required to mount a filesystem is not yet available. For this reason, the rules generate scripts which call other scripts in two stages. The file should be named /etc/udev/rules.d/10-protectedmount.rules. Note that the vendor and product identifiers will be set with an install script to match your hub. This install script is presented later in this chapter.

ACTION==”add”, SUBSYSTEM==”block”, KERNEL==”sd?[1-9]”, ATTRS{idVendor}==”1a40”,

ATTRS{idProduct}==”0101”, ENV{PHIL_MOUNT}=”1”, ENV{PHIL_DEV}=”%k”,

RUN+=”/etc/udev/scripts/protmount.sh %k %n”

ACTION==”remove”, SUBSYSTEM==”block”, KERNEL==”sd?[1-9]”,

ATTRS{idVendor}==”1a40”, ATTRS{idProduct}==”0101”, ENV{PHIL_UNMOUNT}=”1”,

RUN+=”/etc/udev/scripts/protmount3.sh %k %n”

ENV{PHIL_MOUNT}==”1”, ENV{UDISKS_PRESENTATION_HIDE}=”1”,

ENV{UDISKS_AUTOMOUNT_HINT}=”never”, RUN+=”/etc/udev/scripts/protmount2-%n.sh”

ENV{PHIL_MOUNT}!=”1”, ENV{UDISKS_PRESENTATION_HIDE}=”0”,

ENV{UDISKS_AUTOMOUNT_HINT}=”always”

ENV{PHIL_UNMOUNT}==”1”, RUN+=”/etc/udev/scripts/protmount4-%n.sh”

The general format for these rules is a series of statements separated by commas. The first statements, those with double equals (“==”), are matching statements. If all of these are matched, the remaining statements are run. These statements primarily set environment variables and add scripts to a list of those to be run. Any such scripts should run quickly in order to avoid bogging down the system.

The first rule can be broken into matching statements and statements to be executed.

The matching statements are ACTION==”add”, SUBSYSTEM==”block”,

KERNEL==”sd?[1-9]”, ATTRS{idVendor}==”1a40”,

ATTRS{idProduct}==”0101”. This matches when a new device is added; it is a block device; it is named /dev/sdXn (where X is a letter and n is a partition number), and its or a parents’ USB vendor and product ID match those specified. If you only want to match the current device’s attribute and not the parent’s, use ATTR{attributeName} instead of ATTRS{attributeName}. By using ATTRS we are assured the rule will be matched by every device attached downstream from the hub.

The part of the first rule containing commands to run is ENV{PHIL_MOUNT}=”1”,

ENV{PHIL_DEV}=”%k”, RUN+=”/etc/udev/scripts/protmount.sh %k %n” . These statements set an environment variable PHIL_MOUNT equal to 1, set another environment variable PHIL_DEV to the kernel name for the device (sda3, sdb1, etc.), and appends /etc/udev/scripts/protmount.sh to the list of scripts to be run with the kernel name for the device and partition number passed in as parameters.

The second rule is very similar to the first, but it matches when the device is removed. It sets an environment variable PHIL_UNMOUNT to 1 and adds

/etc/udev/scripts/protmount3.sh to the list of scripts to be run (the kernel device name and partition number are again passed in as parameters). The protmount3.sh and protmount4.sh scripts are used to clean up after the device is removed.

The next rule ENV{PHIL_MOUNT}==”1”,

ENV{UDISKS_PRESENTATION_HIDE}=”1”,

ENV{UDISKS_AUTOMOUNT_HINT}=”never”,

RUN+=”/etc/udev/scripts/protmount2.sh” is run later just before the operating system attempts to mount the filesystem. If the PHIL_MOUNT variable has been set, we tell the operating system to hide the normal dialog that is displayed, never automount the filesystem (because it wouldn’t be mounted read-only), and add the protmount2.sh script to the list of things to be executed. If PHIL_MOUNT has not been set to 1, we setup the operating system to handle the device the standard way. The last rule causes protmount4.sh to run if the PHIL_UNMOUNT variable has been set.

We will now turn our attention to the scripts. Two of the scripts protmount.sh and protmount3.sh are used to create the other two protmount2.sh and protmount4.sh, respectively. As previously mentioned, the reason for this is that all of the information needed to properly mount and unmount the filesystem is not available at the same time. The protmount.sh script follows.

!/bin/bash echo “#!/bin/bash” > “/etc/udev/scripts/protmount2-$2.sh” echo “mkdir /media/$1” >> “/etc/udev/scripts/protmount2-$2.sh” echo “chmod 777 /media/$1” >> “/etc/udev/scripts/protmount2-$2.sh” echo “/bin/mount /dev/$1 -o ro,noatime /media/$1” >> “/etc/udev/scripts/protmount2-$2.sh” chmod +x “/etc/udev/scripts/protmount2-$2.sh”

This script echoes a series of commands to the new script. The first line includes the familiar she-bang. The second line creates a directory, /media/{kernel device name} (i.e. /media/sdb2). The third line opens up the permissions on the directory. The fourth line mounts the filesystem as read-only with no access time updating in the newly created directory. The final line in the script makes the protmount2.sh script executable.

The protmount3.sh script is similar except that it creates a cleanup script. The cleanup script is protmount4.sh. The protmount3.sh script follows.

!/bin/bash

echo “#!/bin/bash” > “/etc/udev/scripts/protmount4-$2.sh” echo “/bin/umount /dev/$1” >> “/etc/udev/scripts/protmount4-$2.sh” echo “rmdir /media/$1” >> “/etc/udev/scripts/protmount4-$2.sh” chmod +x “/etc/udev/scripts/protmount4-$2.sh”

An installation script has been created for installing this system. This script takes a vendor and product ID as required parameters. It also takes an optional second product ID. You might be curious as to why this is in the script. If you are using a USB 3.0 hub (recommended) it actually presents itself as two devices, one is a USB 2.0 hub and the other is a USB 3.0 hub. These two devices will have a common vendor ID, but unique product IDs.

!/bin/bash

#

Install script for 4deck addon to “The Deck”

This script will install udev rules which will turn a USB hub

into a magic hub. Every block device connected to the magic hub # will be automatically mounted under the /media directory as read only.

While this was designed to work with “The Deck” it will most likely

work with most modern Linux distros. This software is provided as is

without warranty of any kind, express or implied. Use at your own # risk. The author is not responsible for anything that happens as # a result of using this software.

# Initial version created August 2012 by Dr. Phil Polstra, Sr.

Version 1.1 created March 2015

new versions adds support for a second PID which is required

when using USB 3.0 hubs as they actually present as two hubs unset VID unset PID unset PID2

function usage { echo “usage: sudo $(basename $0) —vid 05e3 —pid 0608 [—pid2 0610]” cat <<EOF

Bugs email: “DrPhil at polstra.org” Required Parameters:

—vid

—pid Optional Parameters: —pid2 EOF exit }

function createRule { cat > /etc/udev/rules.d/10-protectedmount.rules <<-EOF

ACTION==”add”, SUBSYSTEM==”block”, KERNEL==”sd?[1-9]”,

ATTRS{idVendor}==”${VID}”, ATTRS{idProduct}==”${PID}”, ENV{PHIL_MOUNT}=”1”,

ENV{PHIL_DEV}=”%k”, RUN+=”/etc/udev/scripts/protmount.sh %k %n”

ACTION==”remove”, SUBSYSTEM==”block”, KERNEL==”sd?[1-9]”,

ATTRS{idVendor}==”${VID}”, ATTRS{idProduct}==”${PID}”, ENV{PHIL_UNMOUNT}=”1”,

RUN+=”/etc/udev/scripts/protmount3.sh %k %n”

ENV{PHIL_MOUNT}==”1”, ENV{UDISKS_PRESENTATION_HIDE}=”1”,

ENV{UDISKS_AUTOMOUNT_HINT}=”never”, RUN+=”/etc/udev/scripts/protmount2-%n.sh”

ENV{PHIL_MOUNT}!=”1”, ENV{UDISKS_PRESENTATION_HIDE}=”0”,

ENV{UDISKS_AUTOMOUNT_HINT}=”always”

ENV{PHILUNMOUNT}==”1”, RUN+=”/etc/udev/scripts/protmount4-%n.sh” _EOF

if [ ! “$PID2” = “” ] ; then cat >> /etc/udev/rules.d/10-protectedmount.rules <<-EOF

ACTION==”add”, SUBSYSTEM==”block”, KERNEL==”sd?[1-9]”,

ATTRS{idVendor}==”${VID}”, ATTRS{idProduct}==”${PID2}”, ENV{PHIL_MOUNT}=”1”,

ENV{PHIL_DEV}=”%k”, RUN+=”/etc/udev/scripts/protmount.sh %k %n”

ACTION==”remove”, SUBSYSTEM==”block”, KERNEL==”sd?[1-9]”,

ATTRS{idVendor}==”${VID}”, ATTRS{idProduct}==”${PID2}”, ENV{PHIL_UNMOUNT}=”1”,

RUN+=”/etc/udev/scripts/protmount3.sh %k %n”

ENV{PHIL_MOUNT}==”1”, ENV{UDISKS_PRESENTATION_HIDE}=”1”,

ENV{UDISKS_AUTOMOUNT_HINT}=”never”, RUN+=”/etc/udev/scripts/protmount2-%n.sh”

ENV{PHIL_MOUNT}!=”1”, ENV{UDISKS_PRESENTATION_HIDE}=”0”,

ENV{UDISKS_AUTOMOUNT_HINT}=”always”

ENV{PHILUNMOUNT}==”1”, RUN+=”/etc/udev/scripts/protmount4-%n.sh” _EOF fi }

function copyScripts { if [ ! -d “/etc/udev/scripts” ] ; then mkdir /etc/udev/scripts fi cp ./protmount*.sh /etc/udev/scripts/.

} # parse commandline options while [ ! -z “$1” ]; do case $1 in

-h|—help) usage ;;

—vid)

VID=”$2”

;;

—pid)

PID=”$2”

;;

—pid2)

PID2=”$2”

;; esac

shift # consume command line arguments 1 at a time done # now actually do something createRule copyScripts

The script is straightforward. It begins with the usual she-bang, then a couple of environment variables are unset. We see a typical usage function, then a few functions are defined for creating and copying files. Finally, these functions are run at the end of the script.

results matching ""

    No results matching ""