]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mount: add option to specify uid= and gid=
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 9 Dec 2017 09:18:48 +0000 (10:18 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 15 Dec 2017 13:57:07 +0000 (14:57 +0100)
The kernel needs two numbers, but for the user it's most convenient to provide the
user name and have that resolved to uid and gid.

Right now the primary group of the specified user is always used. That's the most
common case anyway. In the future we can extend the --owner option to allow a group
after a colon.

[I added this before realizing that this will not be enough to be used for user
runtime directory. But this seems useful on its own, so I'm keeping this commit.]

man/systemd-mount.xml
src/mount/mount-tool.c

index 87bc2b36eb4c865dbe2563f986a1f2f401632ab6..76ea0550d79d72f413959ad4ef78905b45dbfa8d 100644 (file)
         <listitem><para>Additional mount options for the mount point.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--owner=<replaceable>USER</replaceable></option></term>
+
+        <listitem><para>Let the specified user <replaceable>USER</replaceable> own the mounted file system.
+        This is done by appending <option>uid=</option> and <option>gid=</option> options to the list
+        of mount options. Only certain file systems support this option.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--fsck=</option></term>
 
index da3647e7e2fe50ece1efd1477a21dfe8f5f2d1c0..f82e9dac446700ce5c769d2b13b36f3ff61b517e 100644 (file)
@@ -41,6 +41,7 @@
 #include "strv.h"
 #include "udev-util.h"
 #include "unit-name.h"
+#include "user-util.h"
 #include "terminal-util.h"
 
 enum {
@@ -69,6 +70,8 @@ static usec_t arg_timeout_idle = USEC_INFINITY;
 static bool arg_timeout_idle_set = false;
 static char **arg_automount_property = NULL;
 static int arg_bind_device = -1;
+static uid_t arg_uid = UID_INVALID;
+static gid_t arg_gid = GID_INVALID;
 static bool arg_fsck = true;
 static bool arg_aggressive_gc = false;
 
@@ -89,6 +92,7 @@ static void help(void) {
                "     --discover                   Discover mount device metadata\n"
                "  -t --type=TYPE                  File system type\n"
                "  -o --options=OPTIONS            Mount options\n"
+               "     --owner=USER                 Add uid= and gid= options for USER\n"
                "     --fsck=no                    Don't run file system check before mount\n"
                "     --description=TEXT           Description for unit\n"
                "  -p --property=NAME=VALUE        Set mount unit property\n"
@@ -116,6 +120,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DISCOVER,
                 ARG_MOUNT_TYPE,
                 ARG_MOUNT_OPTIONS,
+                ARG_OWNER,
                 ARG_FSCK,
                 ARG_DESCRIPTION,
                 ARG_TIMEOUT_IDLE,
@@ -139,6 +144,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "discover",           no_argument,       NULL, ARG_DISCOVER           },
                 { "type",               required_argument, NULL, 't'                    },
                 { "options",            required_argument, NULL, 'o'                    },
+                { "owner",              required_argument, NULL, ARG_OWNER              },
                 { "fsck",               required_argument, NULL, ARG_FSCK               },
                 { "description",        required_argument, NULL, ARG_DESCRIPTION        },
                 { "property",           required_argument, NULL, 'p'                    },
@@ -220,6 +226,18 @@ static int parse_argv(int argc, char *argv[]) {
                                 return log_oom();
                         break;
 
+                case ARG_OWNER: {
+                        const char *user = optarg;
+
+                        r = get_user_creds(&user, &arg_uid, &arg_gid, NULL, NULL);
+                        if (r < 0)
+                                return log_error_errno(r,
+                                                       r == -EBADMSG ? "UID or GID of user %s are invalid."
+                                                                     : "Cannot use \"%s\" as owner: %m",
+                                                       optarg);
+                        break;
+                }
+
                 case ARG_FSCK:
                         r = parse_boolean(optarg);
                         if (r < 0)
@@ -422,6 +440,7 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
 }
 
 static int transient_mount_set_properties(sd_bus_message *m) {
+        _cleanup_free_ char *options = NULL;
         int r;
 
         assert(m);
@@ -442,12 +461,25 @@ static int transient_mount_set_properties(sd_bus_message *m) {
                         return r;
         }
 
-        if (arg_mount_options) {
-                r = sd_bus_message_append(m, "(sv)", "Options", "s", arg_mount_options);
+        /* Prepend uid=…,gid=… if arg_uid is set */
+        if (arg_uid != UID_INVALID) {
+                r = asprintf(&options,
+                             "uid=" UID_FMT ",gid=" GID_FMT "%s%s",
+                             arg_uid, arg_gid,
+                             arg_mount_options ? "," : "", arg_mount_options);
                 if (r < 0)
-                        return r;
+                        return -ENOMEM;
         }
 
+        if (options || arg_mount_options) {
+                log_debug("Using mount options: %s", options ?: arg_mount_options);
+
+                r = sd_bus_message_append(m, "(sv)", "Options", "s", options ?: arg_mount_options);
+                if (r < 0)
+                        return r;
+        } else
+                log_debug("Not using any mount options");
+
         if (arg_fsck) {
                 _cleanup_free_ char *fsck = NULL;
 
@@ -1604,6 +1636,23 @@ int main(int argc, char* argv[]) {
                 }
         }
 
+        /* The kernel (properly) refuses mounting file systems with unknown uid=,gid= options,
+         * but not for all filesystem types. Let's try to catch the cases where the option
+         * would be used if the file system does not support it. It is also possible to
+         * autodetect the file system, but that's only possible with disk-based file systems
+         * which incidentally seem to be implemented more carefully and reject unknown options,
+         * so it's probably OK that we do the check only when the type is specified.
+         */
+        if (arg_mount_type &&
+            !streq(arg_mount_type, "auto") &&
+            arg_uid != UID_INVALID &&
+            !fstype_can_uid_gid(arg_mount_type)) {
+                log_error("File system type %s is not known to support uid=/gid=, refusing.",
+                          arg_mount_type);
+                r = -EOPNOTSUPP;
+                goto finish;
+        }
+
         switch (arg_action) {
 
         case ACTION_MOUNT: