7

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

2
  • 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). Apr 20, 2023 at 6:57
  • 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: launchpadlibrarian.net/229524614/pmount.exfat.patch
    – bolind
    Apr 20, 2023 at 7:59

3 Answers 3

8

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
7
  • This only works if the user is in the group "disk", which allows that user to mount anything anywhere, correct?
    – bolind
    Apr 19, 2023 at 11:38
  • 1
    @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
    Apr 19, 2023 at 14:09
  • 2
    @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.)
    – Tom Yan
    Apr 19, 2023 at 14:11
  • 2
    @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, for example, to use a dedicated group for enabling mounting. See its examples for more. Apr 20, 2023 at 5:35
  • 3
    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. Apr 20, 2023 at 5:40
2

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.

0
1

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.

You must log in to answer this question.

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