Score:6

Is there a good way to allow non-root users to mount arbitrary external USB drives on Linux?

cn flag

We have a situation where a site office has a couple of Rocky Linux 8 servers and regularly receives large amounts of data from clients. Data arrives on a variety of external USB hard drives and the occasional USB memory stick. These drives can have all sorts of file systems, but the most common are NTFS and exFAT.

NTFS is natively supported on RL8, but exFAT is not. We have used the fuse-exfat package from rpmfusion. (https://github.com/relan/exfat).

I would like my users, who do not have, and should not have root access, to be able to mount these in a smooth fashion. Previously, we have used pmount, but pmount doesn't play well with exFAT. I think that's because it's FUSE, not because it's exFAT.

Is there a good, secure way to achieve this?

Edit: pmount appears to be a very thin wrapper around mount, and permissions are achieved via a setuid bit on the executable. So basically it's a finite set of mount commands, and exfat is not one of them. There's some discussion here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=755434 and a proposed patch here: launchpadlibrarian.net/229524614/pmount.exfat.patch

user1686 avatar
fr flag
Isn't your NTFS driver FUSE ntfs-3g as well? If I remember correctly, Linux got an in-kernel exFAT driver *before* it got the "good" in-kernel 'ntfs3' driver (with the old 'ntfs' one being… bad).
bolind avatar
cn flag
It could very well be - looking through the source code of pmount, it specifically tries a number of filesystem types, ntfs-3g being one of them and exfat notably absent. See for instance this patch trying to address the problem: https://launchpadlibrarian.net/229524614/pmount.exfat.patch
Score:7
by flag

You could use udisks2, which allows users to manage and mount storage devices without root access.

Setup

  • Install the tool: sudo dnf install udisks2 ntfs-3g fuse-exfat
  • Allow user to manage: sudo usermod -a -G disk <username>

Non-root users in the disk group can use the udisksctl command-line tool to manage and mount external drives.

Replace <username> with the user you want to allow to manage the drives.

Usage examples

  • Mount a drive: udisksctl mount -b /dev/sdXY
  • Unmound a drive: udisksctl unmount -b /dev/sdXY
  • Get information: udisksctl info -b /dev/sdXY
bolind avatar
cn flag
This only works if the user is in the group "disk", which allows that user to mount anything anywhere, correct?
Saxtheowl avatar
by flag
yes, for more security you could also create a new group specifically for mounting external USB drives and limit its scope
Tom Yan avatar
in flag
@bolind Not really. The `mount` command itself has root check IIRC. I don't know if the kernel has anything that guards non-root mounting, but the `disk` group really just allow direct block-level (e.g dd) read/write (it really depends on the permission bits of the devnodes that owned by the disk group). It is irrelevant to mounting (or file-level read/write through a mountpoint) AFAIK.
Tom Yan avatar
in flag
@bolind What really determines which user can use udisks2 to mount a block device is polkit policy. And udisks2 doesn't allow user to specify the mountpoint to use. (Although polkit policy can use user groups to determine which accounts are allowed to do what, I think.)
Nikita Kipriyanov avatar
za flag
@Saxtheowl the addition to the `disk` group is not relevant to how Udisks operates. Its use is explained by Tom Yan and it has nothing to do with Udisks; rather, it's a group owner of all block devices. For Udisks, authorization controls usually defined in `/usr/share/polkit-1/actions/org.freedesktop.UDisks2.policy`, and you can override these in /etc/... and define your own authorization rules as decribed in [man 8 polkit](https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html#polkit-rules), for example, to use a dedicated group for enabling mounting. See its examples for more.
Nikita Kipriyanov avatar
za flag
In short, an authorization rule is a short Javascript function which is called when an action is requested, it is given an action name, and user who initiated it; you can use action.lookup method to know what it asked to mount and where, and decide whether to permit it or not. It is very flexible.
ctrl-alt-delor avatar
in flag
group `disk` can read and write to all disks on the system. This will allow a skilled person/program to do ANYTHING.
Score:1
cn flag

I think I nailed it. Add the following polkit rule to /etc/polkit-1/rules.d/10-allow-usb-mounts.rules:

polkit.addRule(function(action, subject) {
  if (action.id == "org.freedesktop.udisks2.filesystem-mount-other-seat" && subject.isInGroup("groupforthosewhocanmountusbdisks")) {
    var bus = action.lookup("drive.removable.bus");
    if (bus == "usb" || bus == "firewire") {
      polkit.log("polkit rule for mounting USB drives with udisks2")
      polkit.log("Device: " + action.lookup("device"))
      polkit.log("Drive: " + action.lookup("drive"))
      polkit.log("Bus: " + bus)
      polkit.log("Serial: " + action.lookup("drive.serial"))
      polkit.log("Vendor: " + action.lookup("drive.vendor"))
      polkit.log("Model: " + action.lookup("drive.model"))
      return polkit.Result.YES;
    }
  }
});

To test, mount the disk, as a normal user, with:

udisksctl mount -b /dev/sdb

And check the output with journalctl.

Score:1
do flag

You could configure sudo to let users execute some specially crafted script to mount usb drives on a fixed mount point indicating only the device. As an example, they could run:

sudo mount-usb /dev/sdb

where the script will try to mount /dev/usb and mount it, for example, in /mnt/usb, and inform of that to the user. Similarly, we can have an umount-usb script to unmount the drive with:

sudo umount-usb

The mount-usb script could be like this:

#!/bin/bash
# mount-usb: mount drives in /mnt/usb
[ -z "$1" ] && echo "Use: $0 device" && exit
if ! [[ $1 =~ ^/dev/.*$ ]] ; then
   echo "Use /dev/xxx as device"
   exit
fi
mount -t auto -o uid=$SUDO_UID,gid=$SUDO_UID,ro "$1" /mnt/usb
mount | grep /mnt/usb    #-- show result

We use SUDO* vars to get the real id/gid of the calling user and have a simple checking of the device specification with a regex. The corresponding umount-usb will be then:

#!/bin/bash
# umount-usb: unmounts the device in /mnt/usb
umount /mnt/usb

The configuration of sudo is done editing the /etc/sudoers file with the visudo command (or VISUAL=nano visudo to use another editor instead of vi), where we can let some users or group execute certain commands as root without asking for a password. Example for the user john and the group usb-mounters:

Defaults       !lecture
Cmnd_Alias     USBMNT = /root/mount-usb ^/dev/.*$, umount-usb ""
john           ALL=NOPASSWD: USBMNT
%usb-mounters  ALL=NOPASSWD: USBMNT

Note the regex to enable only /dev/xx arguments in mount-usb and the null string to disable them in umount-usb (As described in the sudoers manual). We can omit the test for /dev/xx in the script with this definition, but I prefer to keep it in any case.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.