]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: reimplement X-mount.{owner,group,mode}= by hooks
authorKarel Zak <kzak@redhat.com>
Mon, 30 May 2022 09:47:32 +0000 (11:47 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 3 Jan 2023 11:53:12 +0000 (12:53 +0100)
* "prepare-options hook" parses {owner,group,mode}= options

* "mount-post hook" calls chmod/own

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/meson.build
libmount/src/Makemodule.am
libmount/src/context.c
libmount/src/context_mount.c
libmount/src/hook_owner.c [new file with mode: 0644]
libmount/src/hooks.c
libmount/src/mountP.h

index 011cd3783b17d13a63f2344381177b979a67bdd8..a1d40265959d572378ae07d2835a95451d92c8ce 100644 (file)
@@ -46,6 +46,7 @@ if LINUX
     src/hook_mount_legacy.c
     src/hook_mkdir.c
     src/hook_subdir.c
+    src/hook_owner.c
     src/monitor.c
 '''.split()
 endif
index 90cc4ac266371480ce980941c264b4cb6d03b058..ba229dace78c5219bbe029be71f87c779581fc79 100644 (file)
@@ -35,6 +35,7 @@ libmount_la_SOURCES += \
        libmount/src/hook_mount_legacy.c \
        libmount/src/hook_mkdir.c \
        libmount/src/hook_subdir.c \
+       libmount/src/hook_owner.c \
        libmount/src/monitor.c
 
 if HAVE_BTRFS
index 2c909b19e0b4625e176f416225434a38fe266e30..152704719fa3331f9fae90fb5b8e0cb3d0f8fd55 100644 (file)
@@ -56,10 +56,6 @@ struct libmnt_context *mnt_new_context(void)
        if (!cxt)
                return NULL;
 
-       cxt->tgt_owner = (uid_t) -1;
-       cxt->tgt_group = (gid_t) -1;
-       cxt->tgt_mode = (mode_t) -1;
-
        ruid = getuid();
        euid = geteuid();
 
@@ -159,10 +155,6 @@ int mnt_reset_context(struct libmnt_context *cxt)
        free(cxt->helper);
        free(cxt->orig_user);
 
-       cxt->tgt_owner = (uid_t) -1;
-       cxt->tgt_group = (gid_t) -1;
-       cxt->tgt_mode = (mode_t) -1;
-
        cxt->fs = NULL;
        cxt->mountinfo = NULL;
        cxt->utab = NULL;
index f986cf8eadf4e65778b6d21b3c12f2b1ae615f9f..74cbc0452a97b29a9594402d6f3bea92550d0bf5 100644 (file)
@@ -751,54 +751,6 @@ static int do_mount_by_pattern(struct libmnt_context *cxt, const char *pattern)
        return rc;
 }
 
-/*
- * Process X-mount.owner=, X-mount.group=, X-mount.mode=.
- */
-static int parse_ownership_mode(struct libmnt_context *cxt)
-{
-       int rc;
-       char *value;
-       size_t valsz;
-
-       const char *o = mnt_fs_get_user_options(cxt->fs);
-       if (!o)
-               return 0;
-
-       if ((rc = mnt_optstr_get_option(o, "X-mount.owner", &value, &valsz)) < 0)
-               return -MNT_ERR_MOUNTOPT;
-       if (!rc) {
-               if (!valsz)
-                       return errno = EINVAL, -MNT_ERR_MOUNTOPT;
-
-               if (mnt_parse_uid(value, valsz, &cxt->tgt_owner))
-                       return -MNT_ERR_MOUNTOPT;
-       }
-
-       if ((rc = mnt_optstr_get_option(o, "X-mount.group", &value, &valsz)) < 0)
-               return -MNT_ERR_MOUNTOPT;
-       if (!rc) {
-               if (!valsz)
-                       return errno = EINVAL, -MNT_ERR_MOUNTOPT;
-
-               if (mnt_parse_gid(value, valsz, &cxt->tgt_group))
-                       return -MNT_ERR_MOUNTOPT;
-       }
-
-       if ((rc = mnt_optstr_get_option(o, "X-mount.mode", &value, &valsz)) < 0)
-               return -MNT_ERR_MOUNTOPT;
-       if (!rc) {
-               if (!valsz)
-                       return errno = EINVAL, -MNT_ERR_MOUNTOPT;
-
-               if ((rc = mnt_parse_mode(value, valsz, &cxt->tgt_mode)))
-                       return -MNT_ERR_MOUNTOPT;
-       }
-
-       DBG(CXT, ul_debugobj(cxt, "ownership %d:%d, mode %04o", cxt->tgt_owner, cxt->tgt_group, cxt->tgt_mode));
-
-       return 0;
-}
-
 static int prepare_target(struct libmnt_context *cxt)
 {
        const char *tgt, *prefix;
@@ -907,8 +859,6 @@ int mnt_context_prepare_mount(struct libmnt_context *cxt)
                rc = mnt_context_guess_fstype(cxt);
        if (!rc)
                rc = prepare_target(cxt);
-       if (!rc)
-               rc = parse_ownership_mode(cxt);
        if (!rc)
                rc = mnt_context_prepare_helper(cxt, "mount", NULL);
 
@@ -934,25 +884,6 @@ end:
        return rc;
 }
 
-static int set_ownership_mode(struct libmnt_context *cxt)
-{
-       const char *target = mnt_fs_get_target(cxt->fs);
-
-       if (cxt->tgt_owner != (uid_t) -1 || cxt->tgt_group != (uid_t) -1) {
-               DBG(CXT, ul_debugobj(cxt, "mount: lchown(%s, %u, %u)", target, cxt->tgt_owner, cxt->tgt_group));
-               if (lchown(target, cxt->tgt_owner, cxt->tgt_group) == -1)
-                       return -MNT_ERR_CHOWN;
-       }
-
-       if (cxt->tgt_mode != (mode_t) -1) {
-               DBG(CXT, ul_debugobj(cxt, "mount: chmod(%s, %04o)", target, cxt->tgt_mode));
-               if (chmod(target, cxt->tgt_mode) == -1)
-                       return -MNT_ERR_CHMOD;
-       }
-
-       return 0;
-}
-
 /**
  * mnt_context_do_mount
  * @cxt: context
@@ -1013,9 +944,6 @@ int mnt_context_do_mount(struct libmnt_context *cxt)
        if (mnt_context_is_veritydev(cxt))
                mnt_context_deferred_delete_veritydev(cxt);
 
-       if (!res)
-               res = set_ownership_mode(cxt);
-
        if (!mnt_context_switch_ns(cxt, ns_old))
                return -MNT_ERR_NAMESPACE;
 
@@ -1674,13 +1602,13 @@ int mnt_context_get_mount_excode(
 
                if (rc == -MNT_ERR_CHOWN) {
                        if (buf)
-                               snprintf(buf, bufsz, _("filesystem was mounted, but failed to change ownership to %u:%u: %m"), cxt->tgt_owner, cxt->tgt_group);
+                               snprintf(buf, bufsz, _("filesystem was mounted, but failed to change ownership: %m"));
                        return MNT_EX_SYSERR;
                }
 
                if (rc == -MNT_ERR_CHMOD) {
                        if (buf)
-                               snprintf(buf, bufsz, _("filesystem was mounted, but failed to change mode to %04o: %m"), cxt->tgt_mode);
+                               snprintf(buf, bufsz, _("filesystem was mounted, but failed to change mode: %m"));
                        return MNT_EX_SYSERR;
                }
 
diff --git a/libmount/src/hook_owner.c b/libmount/src/hook_owner.c
new file mode 100644 (file)
index 0000000..5ded9e2
--- /dev/null
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * This file is part of libmount from util-linux project.
+ *
+ * Copyright (C) 2022 Karel Zak <kzak@redhat.com>
+ *
+ * libmount is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ *
+ * This is X-mount.owner=, X-mount.group= and X-mount.mode= implementation.
+ */
+
+#include <sched.h>
+
+#include "mountP.h"
+#include "fileutils.h"
+
+static int hook_prepare_options(struct libmnt_context *cxt, const struct libmnt_hookset *hs, void *data);
+
+struct hook_data {
+       uid_t owner;
+       gid_t group;
+       mode_t mode;
+};
+
+/* de-initiallize this module */
+static int hookset_deinit(struct libmnt_context *cxt, const struct libmnt_hookset *hs)
+{
+       void *data;
+
+       DBG(HOOK, ul_debugobj(hs, "deinit '%s'", hs->name));
+
+       /* remove all our hooks and free hook data */
+       while (mnt_context_remove_hook(cxt, hs, 0, &data) == 0) {
+               if (data)
+                       free(data);
+               data = NULL;
+       }
+
+       return 0;
+}
+
+static int hook_mount_post(
+                       struct libmnt_context *cxt,
+                       const struct libmnt_hookset *hs __attribute__((__unused__)),
+                       void *data)
+{
+       struct hook_data *hd = (struct hook_data *) data;
+       const char *target;
+       int rc = 0;
+
+       assert(cxt);
+
+       if (!hd || !cxt->fs)
+               return 0;
+
+       target = mnt_fs_get_target(cxt->fs);
+       if (!target)
+               return 0;
+
+       if (hd->owner != (uid_t) -1 || hd->group != (uid_t) -1) {
+               DBG(CXT, ul_debugobj(cxt, " lchown(%s, %u, %u)", target, hd->owner, hd->group));
+               if (lchown(target, hd->owner, hd->group) == -1)
+                       return -MNT_ERR_CHOWN;
+       }
+
+       if (hd->mode != (mode_t) -1) {
+               DBG(CXT, ul_debugobj(cxt, " chmod(%s, %04o)", target, hd->mode));
+               if (chmod(target, hd->mode) == -1)
+                       return -MNT_ERR_CHMOD;
+       }
+
+       return rc;
+}
+
+static inline struct hook_data *new_hook_data(void)
+{
+       struct hook_data *hd = calloc(1, sizeof(*hd));
+
+       if (!hd)
+               return NULL;
+
+       hd->owner = (uid_t) -1;
+       hd->group = (gid_t) -1;
+       hd->mode = (mode_t) -1;
+       return hd;
+}
+
+static int hook_prepare_options(
+                       struct libmnt_context *cxt,
+                       const struct libmnt_hookset *hs,
+                       void *data __attribute__((__unused__)))
+{
+       struct hook_data *hd = NULL;
+       const char *o;
+       int rc = 0;
+       char *value;
+       size_t valsz;
+
+       o = mnt_fs_get_user_options(cxt->fs);
+       if (!o)
+               return 0;
+
+       if ((rc = mnt_optstr_get_option(o, "X-mount.owner", &value, &valsz)) < 0)
+               goto fail;
+       if (rc == 0) {
+               if (!valsz)
+                       goto fail;
+               if (!hd) {
+                       hd = new_hook_data();
+                       if (!hd)
+                               goto fail;
+               }
+               if (mnt_parse_uid(value, valsz, &hd->owner))
+                       goto fail;
+       }
+
+       if ((rc = mnt_optstr_get_option(o, "X-mount.group", &value, &valsz)) < 0)
+               goto fail;
+       if (rc == 0) {
+               if (!valsz)
+                       goto fail;
+               if (!hd) {
+                       hd = new_hook_data();
+                       if (!hd)
+                               goto fail;
+               }
+               if (mnt_parse_gid(value, valsz, &hd->group))
+                       goto fail;
+       }
+
+       if ((rc = mnt_optstr_get_option(o, "X-mount.mode", &value, &valsz)) < 0)
+               goto fail;
+       if (rc == 0) {
+               if (!valsz)
+                       goto fail;
+               if (!hd) {
+                       hd = new_hook_data();
+                       if (!hd)
+                               goto fail;
+               }
+               if (mnt_parse_mode(value, valsz, &hd->mode))
+                       goto fail;
+       }
+
+       if (hd) {
+               DBG(CXT, ul_debugobj(cxt, " wanted ownership %d:%d, mode %04o",
+                                       hd->owner, hd->group, hd->mode));
+               rc = mnt_context_append_hook(cxt, hs,
+                               MNT_STAGE_MOUNT_POST,
+                               hd, hook_mount_post);
+               if (rc < 0)
+                       goto fail;
+       }
+       return 0;
+fail:
+       if (rc == 0)
+               rc = -MNT_ERR_MOUNTOPT;
+       free(hd);
+       return rc;
+}
+
+
+const struct libmnt_hookset hookset_owner =
+{
+       .name = "__owner",
+
+       .firststage = MNT_STAGE_PREP_OPTIONS,
+       .firstcall = hook_prepare_options,
+
+       .deinit = hookset_deinit
+};
index 5b345c4a63daf8bd0676963dbd1f82a7131cf495..7e9e9f35b21aef8aac96f617ec32b06e4f42b119 100644 (file)
@@ -26,7 +26,8 @@ static const struct libmnt_hookset *hooksets[] =
 #ifdef __linux__
        &hookset_mkdir,
        &hookset_subdir,
-       &hookset_mount_legacy
+       &hookset_mount_legacy,
+       &hookset_owner
 #endif
 };
 
index 9a748513ed337a5fa81a9f9e9f245cb1911ae60b..c8364a7bf2112d6475905eed300b55b265a031b3 100644 (file)
@@ -306,6 +306,7 @@ struct libmnt_hookset {
 extern const struct libmnt_hookset hookset_mount_legacy;
 extern const struct libmnt_hookset hookset_mkdir;
 extern const struct libmnt_hookset hookset_subdir;
+extern const struct libmnt_hookset hookset_owner;
 
 extern int mnt_context_deinit_hooksets(struct libmnt_context *cxt);
 extern const struct libmnt_hookset *mnt_context_get_hookset(struct libmnt_context *cxt, const char *name);
@@ -355,10 +356,6 @@ struct libmnt_context
        char    *fstype_pattern;        /* for mnt_match_fstype() */
        char    *optstr_pattern;        /* for mnt_match_options() */
 
-       uid_t   tgt_owner;              /* X-mount.owner= */
-       gid_t   tgt_group;              /* X-mount.group= */
-       mode_t  tgt_mode;               /* X-mount.mode= */
-
        struct libmnt_fs *fs;           /* filesystem description (type, mountpoint, device, ...) */
        struct libmnt_fs *fs_template;  /* used for @fs on mnt_reset_context() */