Solaris 11: rmmount - Wann kommt der Bus?

Because the documentation for managing removable media/devices like CDs/DVDs/USB and especially rmmount and friends are pretty shallow, I decided to dig a little bit deeper to find out, how the things fit together. Instead of explaining all the protocols in use and unrelated Linux specific stuff again (see HAL, HAL specs, D‑Bus, Removable Media Enhancements in Solaris) I decided to use a real command to "draw the big picture", explaining the basics and provide appropriate links, so that one may find out the tiny details by itself if needed.

The rough big picture

The following figure shows what basically happens, when rmmount (removable media mount) gets invoked.

SVG image

Step 1: rmmount/libhal

As you can see in the source not much happens in rmmount itself: it just parses command line options and initializes a connection to the D‑Bus using libhal.

Step 2: libhal/D‑Bus

Now libhal is used to create new D‑Bus message, which basically asks to route it to an appropriate service, which is able to invoke the desired method - in this case Mount. Finally the message gets sent to the D‑Bus service using the connection obtained in Step 1.

Step 3: The message broker

When the message arrives at the D‑Bus service usually provided by the dbus‑daemon the service tries to find out, to which service(s) the message should be routed by analyzing it. If an appropriate service is available, the message gets passed to it (that's why the D‑Bus service is often also called "message broker"). But before it actually passes the message, it applies several checks to determine, whether an application and/or the executing user is allowed to send this kind of message! If not, the message gets rejected.

The important thing to note is, that usually on a single machine one systemwide dbus‑daemon instance is running (managed via SMF service svc:/system/dbus:default) and another one for each desktop session (usually started by gdmgnome‑session via /etc/gdm/Xsession/etc/X11/xinit/xinitrc.d/0070.dbus) and none of them utilizes RBAC! Instead they use their own configuration file: /etc/dbus‑1/system.conf (systemwide) and /etc/dbus‑1/session.conf (default for session).

As long as you are logged in at the console/have a desktop session running, this is not really a problem, because the application like rmmount pick up the right address of the instance to use (see step 1): If the environment variable DBUS_SESSION_BUS_ADDRESS is set, this one gets used (which usually corresponds to the session-based instance), otherwise the system wide instance. The session based instance allows per default all messages comming from an applications which is running in the same session, and the system wide instance usually denies "managing" machine local devices like USB, DVD, etc. but loose it up a little bit for the user owning the console and root user - see ls ‑lL /dev/vt/console_user and policy at_console in /etc/dbus‑1/system.d/* for details.

However, if one is logged in from a remote host e.g via ssh, no session based dbus‑daemon is running/gets fired up automatically and thus rmmount and related commands use the systemwide instance. So if one invokes such commands and the system wide instance is using the default configuration, the instance denies passing the message - no matter, whether you actually have the RBAC required privileges or not:

mount of rmdisk /dev/dsk/c1t0d0p0:1 failed: Rejected send message, 2 matched rules; type="method_call", sender=":1.11" (uid=123456 pid=26932 comm="") interface="org.freedesktop.Hal.Device.Volume" member="Mount" error name="(unset)" requested_reply=0 destination="org.freedesktop.Hal" (uid=0 pid=20876 comm=""))

To surmount this obstacle, one may use the following workarounds:

  1. Let the admin of the machine add the appropriate permissions. E.g.

    cat >/etc/dbus-1/system.d/hal-admin.conf<<EOF
    <!DOCTYPE busconfig PUBLIC
     "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
     "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
    <busconfig>
        <!-- allow admin users to [u]mount removable media even if not logged in
             at the console
            /etc/dbus-1/system.d/hal-admin.conf
        -->
        <policy group="admins">
            <allow send_interface="org.freedesktop.Hal.Device.Volume"
                send_destination="org.freedesktop.Hal"/>
            <allow send_interface="org.freedesktop.Hal.Device.Storage"
                send_destination="org.freedesktop.Hal"/>
        </policy>
    </busconfig>
    EOF
    
    svcadm restart dbus
    
  2. Execute the related commands as root - which might not be a good idea

Step 4: D-Bus/hald

Once a message has passed the "security" checks it gets send to the approriate service. The D‑Bus service knows the corresponding address because each service like HAL registers itself after initialization with a certain prefix (HAL with org.freedesktop.Hal) which matches the destination entry in the D‑Bus message.

Step 5: hald

Basically hald is a service, which provides information about the hardware of a machine and, depending on the implementation, is able to manage those hardware devices to a certain degree. Per default it gets managed via the SMF service svc:/system/hal:default.

At startup it reads the configurations files in /etc/hal/fdi/{preprobe,information,policy}/, uses several helper programs to "detect" devices on the machine and to determine their current state (see /usr/lib/hal/hald‑probe‑*), launches several addons to e.g. monitor/pool periodically the state of supported devices (see /usr/lib/hal/hald‑addon-*) and starts /usr/lib/hal/hald‑runner, which gets used to run other external tools like /usr/lib/hal/hal‑{storage,system}‑* on demand (for more details have a look at the HAL specs).

When hald receives a D‑Bus message, it checks, whether it is able to process it immediately/is able answer with the information it has cached for all corresponding devices. If not or if it does not know, how to process the message [yet], it either puts it into its queue or sends the message to the hald-runner for further processing.

Step 6: hald-runner

The hald-runner basically manages [the life cycle of] all external helpers/tools required to fullfill a method request. E.g. for a rmmount request it prepares the environment and executes the hal‑storage‑mount tool with the appropriate parameters.

Step 7: hal-storage-mount

hal‑storage‑mount actually handles the Mount message: It checks, whether it should ignore the message for the given device (unless the sender callee is the root user), verifies that all passed options are allowed/valid and optionally mangles the mount options as needed and determines the mount point to use (usually /media/volumeName|humanReadableDeviceName). Before executing the [re-]mount, it uses the PolicyKit to determine, whether the requesting user is allowed to mount [with possibly additionally passed options]. On Solaris the PolicyKit is implemented using RBAC: libpolkit translates the private HAL privilege names into RBAC privilege names and checks, whether the requesting user is authorized to execute the corresponding action (see also chkauthattr).

Step 8: mount

If the requesting user is authorized to execute the method in question, hal‑storage‑mount creates the mountpoint and finally invokes mount with the given options.

Unfortunately as a non-root/non-console-owner (see problem above) we run into a annoying problem again: because on Solaris 11 hal‑storage‑mount mounts per default a pcfs filesystems using the option mask=077 (remove rwx for group and other) as well as the since Solaris 11.1 documented options owner=0,group=0 (because the mountpoint gets created as root and the __FreeBSD__ addition is not enabled), it actually prevents one from accessing the filesystem:

> cd /media; ls -ld DOS
drwx------   1 root     root        4096 Nov 11 08:30 DOS

> cat /media/.hal-mtab
/dev/dsk/c1t0d0p0:1	123456	0	pcfs	nosuid,owner=0,group=0,mask=077	/media/DOS

> mount -p | grep /media/DOS
/dev/dsk/c1t0d0p0:1 - /media/DOS pcfs - no nosuid,hidden,nofoldcase,clamptime,noatime,timezone=-3600,owner=0,group=0,mask=077

The only workaround for this bug is AFAIK to pass the desired option[s] to rmmount. E.g.:

rmmount -o owner=$USER,group=$GROUP,umask=022 DOS

However, this requires to give the corresponding user the solaris.device.mount.alloptions.removable privilege, which may rise other security issues, because now he is for example allowed to mount ufs/zfs filesystems with the suid option as well ...

Since Illumos currently has no owner,group,mask options for mount_pcfs and the directory gets per default created with 0755 permissions, one is at least able to read it. Because the mount is done by root, the mountpoint directory is owned by root:root after the mount ...

Step 9-12: Send back the result

In these steps nothing really interesting happens: A description of the result of the method invocation get sent back to the sender and finally rmmount exits with a corresponding status code.

Misc. stuff to consider

Having a look at the source code and rough, i.e. simplified picture, additonal question may arise. E.g.:

rmvolmgr

The HAL-aware removable volume manager rmvolmgr basically provides automount like capabilities for removable media and optionally takes care to maintain legacy mountpoint symlinks like /vol/{floppy|cdrom} etc. for ancient software and compatibility for CDE by maintaining /tmp/.removable/notify* files. Usually it runs via the SMF service svc:/system/filesystem/rmvolmgr.

Nowadays legacy mountpoint and CDE compatibility is usually not needed anymore. So the only reason to have the rmvolmgr enabled is to get DVDs/CDROMs/USB sticks automagically mounted on /media/$volname when they get inserted/turned on and umount them, when e.g. the eject button of the device got pressed. To determine, whether a certain action should be taken automatically, rmvolmgr inspects the device properties using HAL. If the device in question is a block.storage_device and has the storage.removable as well as storage.hotpluggable attributes set to true, it takes the appropriate action, if not another service already "manages" the device. As already mentioned above, HAL probes the device to find out the mentioned capabilities, which get complemented by by the HAL configuration files in /etc/hal/fdi/, e.g like in preprobe/10osvendor/20-ignore-fixed-storage.fdi. To determine, what HAL "thinks" about a device, one may use lshal.

So do we need rmvolmgr? At a desktop machine, where things like DVDs and USB sticks are regularly used, the desktop owner probably likes these "autmount" feature/finds it pretty convinient. On the other hand on a server removable media are usually rarely used and even if used, the media gets changed very seldom if at all. So I recommend to not enable the rmvolmgr service on servers - it saves ~ 2 MB RAM, and the process and service list becomes less noisy. Note that tools like rmmount and rmformat do not depend on a running rmvolmgr! Actually, if you know, how to mount the desired volume/filesystem manually using mount, you may even remove the whole system/storage/media-volume-manager and system/storage/removable-media packages. However, this would save you just ~ 500 KB of disk space (incl. documentation) ...

HAL

For a desktop machine this is easy to answer: Many GUI related applications and libraries like brasero, gnome-libs, gnome-applets, X, gstreamer, etc. depend on HAL and often need a running HAL service to work properly/provide its full functionality. So yes, it usually needs to be installed and the SMF service svc:/system/hal:default should be enabled.

On a server the situation is a little bit different: Many admins do not install desktop related GUI applications and tools and abstain from running a X server at all, because those machines are managed remotely connected via ssh and there is no need for GUI apps. In this case, the SMF service svc:/system/hal:default can be disabled, which has beside the less noisy process and service list the advantage, that device states get not polled periodically for nothing (e.g. for removable media every 5 seconds) and saves ~ 20 MB RAM (depends on devices in use). However, than lshal and other related tools like rmmount do not work properly anymore. Anyway, if you know, how to use traditional tools like dmesg, prtconf, prtpicl, scanpci and mount there is no need for the previously mentioned "high level" tools, what means, one may uninstall the whole system/hal package. It would save you about 500..900 KB of disk space ...

D‑Bus

Here the situation is similar to HAL. Many GUI based applications and libraries are using the the D‑Bus for IPC (InterProcessCommunication) - not only for HAL related stuff and thus require a running systemwide dbus-daemon instance as well as a per login session based dbus-daemon instance. So disabling the SMF service svc:/system/dbus:default is usually not a goid idea.

On the server however, there are only very few tools, which require a D‑Bus. Disabling the service saves ~ 1 MB RAM and makes the system less noisy as already mentioned above. If you can abstain from rmvolmgr and HAL, you may also uninstall the related packages: system/library/policykit, system/library/libdbus-glib, system/library/dbus, system/library/libdbus which saves you ~ 600..1800 KB. If one doesn't use net-snmp, one may now even remove the related packages: system/data/hardware-registry, system/fault-management/fm-snmp-mib, library/python-2/net-snmp-26, system/management/snmp/net-snmp (at least when the IPS pkg tool got fixed), which would save you additional ~ 6..7 MB of disk space.

Summary

On a desktop machine the D‑Bus, HAL and rmvolmgr services should be enabled. On a server they should be disabled (or run on demand, only) which saves you ~ 25 MB RAM. They might be even not installed, which saves you ~ 10 MB of disk space. Actually it is recommanded to install on servers the software package group solaris-small-server only, which has no dependencies on the D‑Bus, HAL and rmvolmgr and thus the related packages are not installed per default. However, depending on what you are doing with your server, you mileage may vary ...

Copyright (C) 2012 Jens Elkner (jel+s11@cs.uni-magdeburg.de)