User mounting of Removable Devices on FreeBSD 5.3

CAIA Technical Report 041130A

Jason But
December 1st, 2004

Introduction

FreeBSD is a UNIX oriented operating system which is also the default desktop Operating System (OS) for many at the Centre for Advanced Internet Architectures (CAIA). While documentation for FreeBSD, its usage and configuration is plentiful and generally complete, it is often scattered and difficult to apply to generic desktop situations. This lack of straight forward HOW-TO documentation, either within the official documentation or associated web-sites located through the use of Google is often frustrating. The topic of this article, allowing general users (non-root) to mount and unmount removable filesystems (such as the Floppy Drive, CDROM or a USB Memory Stick) is one such issue. While all the information contained within this article is available online, it is often spread around numerous web-pages, and written in a way that makes it difficult to implement.

In the same vein as our recent article on installing Microsoft Office 2000 on a FreeBSD system, I present this short report with a step-by-step procedure in allowing regular users to be able to mount removable filesystems. Note that the procedures within this report may lessen the security of your system by allowing greater capability for malice by a regular user, in an environment of a desktop PC typically used by a single (or trusted) persons, this risk is minimal. However, you should consider your security requirements carefully before opening up mounting of filesystems to non-root users. I would not recommend allowing this functionality on server or general public access computers.

The task that we wish to allow is this:

Granting mount/umount access to all users.

The first step is to allow users to run the mount command to actually mount a filesystem and to allow them to run the umount command. This is done by adding the following line to your /etc/sysctl.conf file.

    vfs.usermount=1

This option will be set within the kernel at next system boot, to enable it immediately run the following command as root:

    sysctl vfs.usermount=1

It is important to note that while setting this variable allows ALL users to run the mount/umount commands to mount and unmount filesystems, mounting and unmounting will only be possible if:

The second issue is typically not a problem, users can always generate an empty directory to host the mount. The first issue is what allows us to restrict access to certain devices for mounting by particular users. However, this security is limited, while we can stop a user from mounting a device entirely, when permission is granted to mount the device, that user can mount it with whatever mount options they like.

Static Removable Filesystems - Floppy Drive and CDROM

The device names described in this section may differ depending on your system, on my system the floppy drive is located at (/dev/fd0) and the CDROM at (/dev/acd0).

Permission to mount

I will implement security in this system by allowing only root and members of the group (mounters) to mount these devices. In order to allow anybody from the mounters group to mount the floppy and cdrom devices, the device ownership and permission settings need to be changed to:

    crw-rw---- root:mounters

While this command can be issued by root, the device owner and permissions will be reset the next time the system is restarted, in order to make this change permanent, we need to add the following entries to the /etc/devfs.conf file.

    # Allow members of the group mounters to mount the floppy disk.
    own     /dev/fd0        root:mounters
    perm    /dev/fd0        0660

    # Allow members of the group mounters to mount the cdrom.
    own     /dev/acd0       root:mounters
    perm    /dev/acd0       0660
    

The next time the system is started, all members of the group mounters may mount and unmount the CDROM and Floppy Drive to directories that they own. In order to allow all users permission to mount a device, set the permission value to 0666.

A regular user can now issue the commands:

    mkdir ~/cdrom
    mount -t cd9660 /dev/acd0 ~/cdrom
    umount ~/cdrom
  

Simplifying the mount process

The standard technique of adding an entry to the /etc/fstab file. There can be multiple entries in the same fstab file for a single device - this allows an entry for each user to use. All users cannot use the same mount point since they all cannot own the generic mount point. The relevant entries in my fstab file look like this:

    /dev/fd0                /mnt/floppy         auto    noauto          0       0
    /dev/fd0                /home/jbut/floppy   auto    noauto          0       0
    /dev/acd0               /mnt/cdrom          cd9660  ro,noauto       0       0
    /dev/acd0               /home/jbut/cdrom    cd9660  ro,noauto       0       0
  

The mount points in /mnt are owned by root while the mount points in /home/jbut are owned by jbut. Now user jbut can mount the CDROM device through simple execution of:

    mount ~/cdrom

KDE Desktop Integration

The above settings allow for a user to mount and unmount a CDROM or floppy drive from the terminal. As you notice, I have configured two mount points in my home directory to be associated with entries in /etc/fstab so that I can easily mount my own removable file systems without running su. What I would really like to do is to be able to mount and unmount these devices by clicking on the desktop. To do this I perform the following steps.

  1. Right-click on the desktop.
  2. Select Create New->Device->Floppy Device...
  3. Change the name and icons to whatever you like.
  4. Select the device from the drop down list in the "Device" tab. This list contains all entries from the /etc/fstab file, select the one where you own the directory for the floppy device - in my case (/home/jbut/floppy)
  5. Repeat the above procedure for the CDROM, instead selecting Create New->Device->CD-ROM Device...
We now the following abilities:

Dynamic Removable Filesystems - USB Memory Sticks

The USB memory stick behaves differently to a floppy/cdrom drive. In the previous cases, the devices are detected at system boot and created in the /dev directory. USB devices are automatically detected upon attachment by the USB driver, which then creates the device in /dev dynamically, when the USB device is removed, the device is removed from /dev.

This causes some complications, a USB Memory stick is typically assigned the device name /dev/da0 (on my system). If an entry for this device is put in /etc/devfs.conf, it will typically not be applied since the permissions and ownership settings listed in /etc/devfs.conf are only applied at system boot, and the device /dev/da0 is not created until the USB device is physically inserted.

However, this also provides an opportunity to completely automate the mounting procedure since we can trap the insertion of the USB Memory Stick and automatically mount it.

My Goal

If a user is logged on via KDE: If a user is logged on via a terminal:

USBD Daemon

The USBD Daemon appears to be the best option, infact I achieved most of the above goals using this process. The sticking point came upon physical detachment of the device. This action was not properly detected by the daemon which could not be configured to execute a script upon occurance.

DEVD Daemon

The DEVD Daemon detects the creation and deletion of devices and can have actions assigned to these events. We can easily extend the configured devices by adding appropriate files to the /usr/local/etc/devd directory. I created the following file (umass.conf to detect and perform tasks for USB Memory Sticks:

    attach 100 {
            device-name "umass[0-9]+";
            action      "/bin/sleep 3; /etc/rc.d/devfs restart; /usr/local/share/umass/umassaction attach $device-name";
    };
    
    detach 100 {
            device-name "umass[0-9]+";
            action      "/usr/local/share/umass/umassaction detach $device-name";
    };
  
When a USB Memory stick is inserted, it is detected as a umass device. The entries listed above allow devd to detect the insertion and removal of a umass device. Upon insertion we:

  1. Sleep for three seconds to allow time for the device (/dev/da0) to be created.
  2. Restart devfs, allowing the ownership and permissions of the newly created device to be changed.
  3. Run the umassaction helper script to perform the attach task on the properly created and permissioned device.
When the umass device is physically removed we run the umassaction helper script to perform the detach task on the device. Note that this will not unmount the device since it will only be called AFTER the device is removed, it is always necessary to manually unmount the device prior to physical removal.

We need to add the following lines to the /etc/devfs.conf file to allow members of the group mounters to mount and unmount the USB Memory Stick:

    # Allow members of the group mounters to mount a USB Memory Stick.
    own     /dev/da0        root:mounters
    perm    /dev/da0        0660
  
To allow a simple mount and unmount by the user, we also need the appropriate entry in the /etc/fstab file. My configuration file has:

    /dev/da0                /mnt/usbflash       auto    noauto          0       0
  
The script that is executed by both attach and detach actions (/usr/local/share/umass/umassaction) is:

    #!/bin/sh
     
    # Find out who, if any user is logged on via XWindows
    USR=`who | grep :0 | cut -f 1 -d " "`
    
    # If nobody, exit with no error (the device already has proper permissions via
    # the restart of devfd.
    if [ $USR = '' ]; then
        exit 0
    fi
    
    case $1 in
        attach)    chown $USR /mnt/usbflash
                   su $USR -c "/sbin/mount /mnt/usbflash"
                   cp /usr/local/share/umass/USBDevice /home/$USR/Desktop/.
                   ;;

        detach)    chown root /mnt/usbflash
                   rm /home/$USR/Desktop/USBDevice
                   ;;

        *)         exit 1
    esac
  
When executed upon USB Memory stick insertion (and after the permissions for /dev/da0 have been set), this script will:

  1. Determine who is logged onto the system via XWindows. This is done by:
    1. who returns a list of all users logged onto the system and from which terminal they have logged on from.
    2. Only one user can be logged on via XWindows, they are logged on from the terminal :0 - the grep command filters the output of who to the single entry of interest.
    3. We use cut to extract the first field of this line and return the username of the currently logged on user.
  2. If nobody is logged on via XWindows, simply exit the script. As /dev/da0 already has proper permissions, the user can mount/unmount the device from the command line.
  3. Change ownership of the common mount point /mnt/usbflash to the currently logged on user (so the USB Memory Stick can be mounted to that point by the user).
  4. Execute the command mount /mnt/usbflash as the currently logged-on user. This will perform the mount in a way that the user can later unmount the device.
  5. Copy the file USBDevice to the users desktop. This contains the icon that allows the user to open/unmount/remount the USB Memory Stick at will.
The user MUST unmount the memory stick prior to removal, this can be done via the icon on the desktop or via the command line. Upon removal, the umassaction script will:

  1. Determine who is logged onto the system via XWindows.
  2. If nobody is logged on via XWindows, simply exit the script.
  3. Change ownership of the common mount point /mnt/usbflash back to root.
  4. Delete the USB Flash Drive device icon from the users desktop.
The file USBDevice which is copied to the users desktop is a standard .desktop file to specify a device. It is stored in /usr/local/share/umass/USBDevice and its contents are:

    [Desktop Entry]
    Dev=/dev/da0
    Name=USB Flash Disk
    Encoding=UTF-8
    Icon=usbpendrive_unmount
    MountPoint=/mnt/usbflash
    ReadOnly=false
    Type=FSDevice
    UnmountIcon=usbpendrive_unmount
  
The process when a USB memory stick is inserted is now:

  1. Device physically attached.
  2. Device detected by USB Daemon.
  3. Daemon sleeps for three seconds.
  4. Device /dev/da0 created.
  5. devfs restarted and permissions and ownership of newly created device are changed.
  6. Device mounted as the currently logged on user under XWindows.
The user is able to repeatedly mount and unmount the USB device while it is physically connected to the computer.

It is imperative to unmount the device prior to physical removal. If filesystem writes are pending, the USB Memory stick can become corrupted. The proper procedure is to:

  1. Unmount the mounted USB Memory Stick.
  2. Physically remove the device.
The umount cannot be performed in the (detach) option in the DEVD configuration since these commands are only executed after the device has been physically removed and we need to unmount the device prior to physical removal.

The fact that we can automatically detect the USB Memory Stick and schedule actions to occur upon insertion and deletion mean that we can achieve a more Mac OS X like result. Insertion creates a device on the desktop and removal deletes it. Mounting is automatic and owned by the current user.

Conclusion

The information presented in this report is available in many places, but typically not all together in a single place. While I am sure that many others have already achieved something similar to that listed here, they have not adequately produced a useful HOWTO type documentation. In this report I hope to have achieved this, described all the steps and reasons I have taken to allow me to mount these devices on my system without having to go the terminal and without having to be logged on as root to do so.


 

Last Updated: Thursday 2-Dec-2004 20:38:42 EST | Maintained by: Jason But (jbut@swin.edu.au) | Authorised by: Grenville Armitage ( garmitage@swin.edu.au)