diff --git a/data/80-udisks.rules b/data/80-udisks.rules
index d1351f3..057d5df 100644
--- a/data/80-udisks.rules
+++ b/data/80-udisks.rules
@@ -223,5 +223,21 @@ ENV{ID_VENDOR}=="Sony", ENV{ID_MODEL}=="PRS*Launcher", ENV{UDISKS_PRESENTATION_H
##############################################################################################################
+# Additional mount options passed to udisks-daemon to allow sysamins to restrict mount to read-only or "noexec"
+# for example:
+#
+# ENV{UDISKS_MOUNT_OPTIONS}="ro,noexec"
+# ENV{UDISKS_MOUNT_OPTIONS_ALLOW}="exec,noexec,nodev,nosuid,atime,noatime,nodiratime,ro,rw,sync,dirsync"
+#
+# use specific charset for FAT filesystems
+#
+# ENV{ID_FS_TYPE}=="vfat",
+# ENV{UDISKS_MOUNT_OPTIONS}="utf8=0,iocharset=iso8859-15"
+#
+# mount all USB devices RO
+#
+# SUBSYSTEMS="usb", ENV{ID_FS_USAGE}=="filesystem",
+# ENV{UDISKS_MOUNT_OPTIONS}="ro"
+
LABEL="udisks_end"
diff --git a/doc/man/udisks7.xml b/doc/man/udisks7.xml
index c5d0a55..e268a3c 100644
--- a/doc/man/udisks7.xml
+++ b/doc/man/udisks7.xml
@@ -74,6 +74,22 @@
icon theme specification.
+
+
+
+ Additional mount options to be appended to the existing
+ mount options. Format is a comma separated list of options to pass to
+ mount.
+
+
+
+
+
+ If set, this restricts the options allowed in mount.
+ Format is a comma separated list of possible options allowed to be
+ passed to mount (e.g. "exec,noexec,nodev,nosuid,atime,noatime,nodiratime,ro,rw,sync,dirsync,uid=,gid=")
+
+
The properties are used to describe what
diff --git a/src/device-private.c b/src/device-private.c
index 22a0d35..9197fd8 100644
--- a/src/device-private.c
+++ b/src/device-private.c
@@ -552,6 +552,30 @@ device_set_device_presentation_icon_name (Device *device,
}
void
+device_set_device_mount_options (Device *device,
+ const gchar *value)
+{
+ if (G_UNLIKELY (g_strcmp0 (device->priv->device_mount_options, value) != 0))
+ {
+ g_free (device->priv->device_mount_options);
+ device->priv->device_mount_options = g_strdup (value);
+ emit_changed (device, "device_mount_options");
+ }
+}
+
+void
+device_set_device_mount_options_allow (Device *device,
+ const gchar *value)
+{
+ if (G_UNLIKELY (g_strcmp0 (device->priv->device_mount_options_allow, value) != 0))
+ {
+ g_free (device->priv->device_mount_options_allow);
+ device->priv->device_mount_options_allow = g_strdup (value);
+ emit_changed (device, "device_mount_options_allow");
+ }
+}
+
+void
device_set_device_mounted_by_uid (Device *device,
guint value)
{
diff --git a/src/device-private.h b/src/device-private.h
index a6db7f2..f4b1fb3 100644
--- a/src/device-private.h
+++ b/src/device-private.h
@@ -130,6 +130,8 @@ struct DevicePrivate
gboolean device_presentation_nopolicy;
char *device_presentation_name;
char *device_presentation_icon_name;
+ char *device_mount_options;
+ char *device_mount_options_allow;
char *id_usage;
char *id_type;
@@ -286,6 +288,8 @@ void device_set_device_presentation_hide (Device *device, gboolean value);
void device_set_device_presentation_nopolicy (Device *device, gboolean value);
void device_set_device_presentation_name (Device *device, const gchar *value);
void device_set_device_presentation_icon_name (Device *device, const gchar *value);
+void device_set_device_mount_options (Device *device, const gchar *value);
+void device_set_device_mount_options_allow (Device *device, const gchar *value);
void device_set_id_usage (Device *device, const gchar *value);
void device_set_id_type (Device *device, const gchar *value);
diff --git a/src/device.c b/src/device.c
index c4a83ff..d00c7fb 100644
--- a/src/device.c
+++ b/src/device.c
@@ -214,7 +214,9 @@ enum
PROP_DEVICE_PRESENTATION_NOPOLICY,
PROP_DEVICE_PRESENTATION_NAME,
PROP_DEVICE_PRESENTATION_ICON_NAME,
-
+ PROP_DEVICE_MOUNT_OPTIONS,
+ PROP_DEVICE_MOUNT_OPTIONS_ALLOW,
+
PROP_JOB_IN_PROGRESS,
PROP_JOB_ID,
PROP_JOB_INITIATED_BY_UID,
@@ -485,6 +487,12 @@ get_property (GObject *object,
case PROP_DEVICE_PRESENTATION_ICON_NAME:
g_value_set_string (value, device->priv->device_presentation_icon_name);
break;
+ case PROP_DEVICE_MOUNT_OPTIONS:
+ g_value_set_string (value, device->priv->device_mount_options);
+ break;
+ case PROP_DEVICE_MOUNT_OPTIONS_ALLOW:
+ g_value_set_string (value, device->priv->device_mount_options_allow);
+ break;
case PROP_JOB_IN_PROGRESS:
g_value_set_boolean (value, device->priv->job_in_progress);
@@ -1117,6 +1125,20 @@ device_class_init (DeviceClass *klass)
NULL,
NULL,
G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_MOUNT_OPTIONS,
+ g_param_spec_string ("device-mount-options",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_MOUNT_OPTIONS_ALLOW,
+ g_param_spec_string ("device-mount-options-allow",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_JOB_IN_PROGRESS, g_param_spec_boolean ("job-in-progress",
NULL,
@@ -1796,7 +1818,9 @@ device_finalize (GObject *object)
g_ptr_array_free (device->priv->device_mount_paths, TRUE);
g_free (device->priv->device_presentation_name);
g_free (device->priv->device_presentation_icon_name);
-
+ g_free (device->priv->device_mount_options);
+ g_free (device->priv->device_mount_options_allow);
+
g_free (device->priv->id_usage);
g_free (device->priv->id_type);
g_free (device->priv->id_version);
@@ -2277,6 +2301,16 @@ diff_sorted_lists (GList *list1,
/* ---------------------------------------------------------------------------------------------------- */
+/* update udisks_mount_options* properties */
+static gboolean
+update_mount_options (Device *device)
+{
+ device_set_device_mount_options (device, g_udev_device_get_property (device->priv->d, "UDISKS_MOUNT_OPTIONS"));
+ device_set_device_mount_options_allow (device, g_udev_device_get_property (device->priv->d, "UDISKS_MOUNT_OPTIONS_ALLOW"));
+
+ return TRUE;
+}
+
/* update id_* properties */
static gboolean
update_info_presentation (Device *device)
@@ -4642,6 +4676,10 @@ update_info (Device *device)
if (!update_info_presentation (device))
goto out;
+ /* device_mount_options property */
+ if (!update_mount_options (device))
+ goto out;
+
/* id_* properties */
if (!update_info_id (device))
goto out;
@@ -5979,6 +6017,52 @@ is_uid_in_gid (uid_t uid,
}
static gboolean
+is_mount_option_allowed_for_dev (Device *device,
+ const char *option)
+{
+ int n;
+ gboolean allowed;
+ const char *ep;
+ gsize ep_len;
+ gchar *options_allowed;
+ gchar **allow;
+
+ options_allowed = device->priv->device_mount_options_allow;
+
+ if (options_allowed == NULL || strlen (options_allowed) == 0)
+ return TRUE;
+
+ allowed = FALSE;
+ allow = g_strsplit (options_allowed, ",", 0);
+
+ for (n = 0; allow != NULL && allow[n] != NULL; n++)
+ {
+ ep = strstr (allow[n], "=");
+ if (ep != NULL && ep[1] == '\0')
+ {
+ ep_len = ep - allow[n] + 1;
+ if (strncmp (allow[n], option, ep_len) == 0)
+ {
+ allowed = TRUE;
+ goto out;
+ }
+ }
+ else
+ {
+ if (strcmp (allow[n], option) == 0)
+ {
+ allowed = TRUE;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ g_strfreev (allow);
+ return allowed;
+}
+
+static gboolean
is_mount_option_allowed (const FSMountOptions *fsmo,
const char *option,
uid_t caller_uid)
@@ -6308,6 +6392,11 @@ device_filesystem_mount_authorized_cb (Daemon *daemon,
/* validate mount options and check for authorizations */
s = g_string_new ("uhelper=udisks,nodev,nosuid");
+ if (device->priv->device_mount_options != NULL && strlen (device->priv->device_mount_options) > 0)
+ {
+ g_string_append_printf (s, ",%s", device->priv->device_mount_options);
+ }
+
for (n = 0; options[n] != NULL; n++)
{
const char *option = options[n];
@@ -6328,6 +6417,13 @@ device_filesystem_mount_authorized_cb (Daemon *daemon,
goto out;
}
+ /* Only add that option if it's listed in udev's UDISKS_MOUNT_OPTIONS_ALLOW */
+ if (!is_mount_option_allowed_for_dev (device, option))
+ {
+ g_print ("**** NOTE: Ignoring option %s, not allowed by UDISKS_MOUNT_OPTIONS_ALLOW\n", option);
+ continue;
+ }
+
g_string_append_c (s, ',');
g_string_append (s, option);
}