0

I wrote a new udev rule to create a symlink to a luks-encrypted partition on a USB flash drive when the drive is plugged in. The new udev rule I wrote does create the symlink to the USB drive's partition that is luks-encrypted. But, when run 'cryptsetup luksOpen' specifying the symlink to get the /dev/mapper/ object that I can then mount the ext4 filesystem, the symlink disappears as soon as the cryptsetup command has ended. That is not expected and I want the symlink to remain until the USB drive is ejected.

The udev rule:

SUBSYSTEM!="block", GOTO="usb_luks_rules_end"
ENV{DEVTYPE}!="partition",  GOTO="usb_luks_rules_end"
ACTION=="add", ENV{ID_FS_TYPE}=="crypto_LUKS", SYMLINK+="myusbluks"
LABEL="usb_luks_rules_end"

I start with the drive unplugged and therefore no symlink:

# ls /dev/my*
ls: cannot access /dev/my*: No such file or directory

I plug in the usb flash drive that has one luksFormat-ed partition on it. Inside the encrypted partition is an ext4 filesystem. The usb drive becomes /dev/sdc. I want my symlink to point at that partition so that I can 'cryptsetup luksOpen' the symlink name instead of specifying the unpredictable /dev/sdc1 name.

# ls -l /dev/my*
lrwxrwxrwx. 1 root root 4 Mar 24 15:51 /dev/myusbluks -> sdc1

The udev rule worked and created the symlink just like I expected. Now I run cryptsetup luksOpen on the symlink, and upon regaining control, the symlink is gone!

# cryptsetup luksOpen /dev/myusbluks cr_diskbackup
Enter passphrase for /dev/myusbluks: (I enter passphrase successfully.)
# ls -l /dev/my*
ls: cannot access /dev/my*: No such file or directory
# ls -l /dev/mapper/cr_diskbackup
lrwxrwxrwx. 1 root root 8 Mar 24 15:53 /dev/mapper/cr_diskbackup -> ../dm-92
# blkid /dev/mapper/cr_diskbackup
/dev/mapper/cr_diskbackup: LABEL="backupdisk1" UUID="54e2dfcb-20d9-4699-8f7c-0834fda1b4a6" TYPE="ext4"
# ls -l /dev/sdc1
brw-rw----. 1 root disk 8, 33 Mar 24 15:53 /dev/sdc1
# blkid /dev/sdc1
/dev/sdc1: UUID="dd5c374e-963f-4604-8ca3-d271a26abc90" TYPE="crypto_LUKS"

I certainly have accomplished one of the goals of using the symlink to cryptsetup luksOpen the drive instead of having to use "/dev/sdc1". But, I would like for the symlink to persist until the usb drive is physically unplugged.

I ran strace on the same command after another setup. I can see the symlink name being opened and stat-ed, but I do not see anything deleting the symlink in the cryptsetup strace.

The following is from "udevadm monitor" from the point when cryptsetup luksOpen is issued:

KERNEL[2064243.853683] change   /devices/pci0000:00/0000:00:14.0/usb1/1-10/1-10.2/1-10.2:1.0/host29/target29:0:0/29:0:0:0/block/sdc/sdc1 (block)
KERNEL[2064243.854830] add      /devices/virtual/bdi/253:92 (bdi)
KERNEL[2064243.855452] add      /devices/virtual/block/dm-92 (block)
UDEV  [2064243.856682] add      /devices/virtual/bdi/253:92 (bdi)
KERNEL[2064243.856781] change   /devices/virtual/block/dm-92 (block)
UDEV  [2064243.858320] add      /devices/virtual/block/dm-92 (block)
UDEV  [2064243.897808] change   /devices/pci0000:00/0000:00:14.0/usb1/1-10/1-10.2/1-10.2:1.0/host29/target29:0:0/29:0:0:0/block/sdc/sdc1 (block)
UDEV  [2064244.124652] change   /devices/virtual/block/dm-92 (block)

The fact that a "change" event is occurring is probably involved in this. I am not sure whether it is cryptsetup or device mapper that is causing that. But since /dev/sdc1 remains as a device after cryptsetup luksOpen completes, I do not understand why the symlink is not left alone so that it can continue to point at that same device. On the system where I am doing this, there can be other USB drives without a luks partition that might be plugged in. Thus, the desire for a symlink to the luks partition if it exists.

What am i missing here? Is a symlink to the base encrypted partition considered to be some kind of security problem if it has been opened and something is making sure such a symlink does not exist?

4
  • Try: udevadm control --reload-rules; udevadm trigger Commented Mar 26, 2021 at 2:50
  • If I hot-plug the USB stick, then the symlink is created. If I perform the suggested udevadm control --reload-rules; udevadm trigger, then the symlink is removed if it already exists because of the hot-plug. Commented Mar 26, 2021 at 15:38
  • Furhter research shows that changing the ACTION match in the udev rule from "add" to "add|change" will cause rule to create the symlink again. This is moderately ok if always specifying a static name AND if a second luks partition is not found. The root of the problem I believe is the second "add" event for that udev is driving for the partition as noted in the 'udevadm monitor' listing in the oroginal post. Why would cryptsetup cause /dev/sdc1 to add /dev/sdc1 again? Commented Mar 27, 2021 at 14:17
  • Here's how I do it but for different reasons. I place following "UUID=5E71-3EAF /media/usb-drive vfat defaults 0 3" in /etc/fstab. Then I mount the drive by typing "mount -a" as root, and then I use the icon on the desktop to "eject" the usb drive. It can be ext4 - doesn't have to be a vfat filesystem. And you can probably add other mount options. I didn't mess with udev. The path to the drive never changes. Commented Mar 27, 2021 at 21:46

1 Answer 1

0

I have resolved this to my satisfaction using a more elaborate helper script. The helper script

For reasons that I do not understand, I confirmed that the 2nd udev "change" event that occur after entering a

cryptsetup luksOpen /dev/asymlinkname cr_diskbackup

command is resulting in the symlink disappearing.
I switched the rule logic to "add|change", and also added a helper script. The helper script is a modification of one found here: udev rule for assigning known symlinks for identical usb serial devices. The modification is the addition of logic to find any existing symlink(s) in the /dev directory that point to the luks partition (usually /dev/sdc1, but not guaranteed). If one is found, print the suffix number of the symlink to stdout. Udev reads the number and uses it as a suffix to (re)create the symlink with that name. Cryptsetup luksOpen continues to work as before, mysteriously deleting the symlink to the block device even though the block device remains. But with the helper script, now the symlink is present after the luksOpen because it is created again by the udev rule action for the "change" event.

The updated udev rule:

SUBSYSTEM!="block", GOTO="my_usb_luks_rules_end"
ENV{DEVTYPE}!="partition",  GOTO="my_usb_luks_rules_end"
ACTION=="add|change", ENV{ID_FS_TYPE}=="crypto_LUKS", PROGRAM="/usr/local/sbin/my-unique-usb-luks-num /dev myusbluks $env{DEVNAME}", SYMLINK+="myusbluks%c"
LABEL="my_usb_luks_rules_end"

The /usr/local/sbin/my-unique-usb-luks-num script:

#!/bin/bash

if [ $# -ne 3 ]; then
    printf "Usage: $0 location prefix devicename\n" >&2
    exit 1
fi

location="$1"
prefix="$2"
devname="$3"

# Find any symlinks in the location that may already
# exist to our device. Save only the first one.
old_symlink=$( find $location -maxdepth 1 \
                    -lname "$(basename ${devname})" \
                    -name "$prefix*" |
                    sort -n | head -n 1 )

# If we found any symlinks with our prefix to the specified device, then print
# its numeric suffix to stdout for it to be "$result" (%c) in the caller udev
# rule.
if [ "${old_symlink}" != "" ]; then
   devbase=$(basename ${old_symlink})
   printf "${devbase##$prefix}\n"
   exit
fi

# No symlink was already in existence, so find a unique new suffix number.
for ((index=0; index<256; index++)); do
  if [ ! -e "$location/$prefix$index" ]; then
     # Merely print this to our stdout for it to be $result (%c) in caller udev
     # rule. Then exit.
     printf "$index\n"
     exit
  fi
done
# If we did not exit above, we printed (returned) nothing.
exit 1

Plugging in the usb drive with the luks partition results in:

/dev/myusbluks0

to be created. If a second usb drive with a luks partition is plugged in concurrently, that luks partition will get a symlink

/dev/myusbluks1

If I

cryptsetup luksOpen /dev/myusbluks0  cr_diskbackup

the symlink will still be present and pointing to the device as prior to the cryptsetup luksOpen. And, the unique number suffices make it a bit more bullet proof.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .