]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: fix MS_REMOUNT emulation by mount_setattr()
authorKarel Zak <kzak@redhat.com>
Thu, 23 Mar 2023 14:25:00 +0000 (15:25 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 23 Mar 2023 14:25:00 +0000 (15:25 +0100)
The classic mount(MS_REMOUNT) means that all unspecified MS_NOxxx
flags are remove (except MS_NOATIME). We need to follow this semantic
when emulate remount by mount_setattr(), because "mount -o remount /"
is the way how (for example) systemd resets root filesystem to default
(e.g. ro->rw, etc.)

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2180593
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/hook_mount.c
libmount/src/optlist.c

index b535382b4da8960b0f74c7dbfb1d98cbf5b4e653..39fc841d509bf977c71accebf385f02068bd5a73 100644 (file)
@@ -610,7 +610,7 @@ static int hook_prepare(struct libmnt_context *cxt,
        /* call mount_setattr() */
        if (!rc
            && cxt->helper == NULL
-           && (set != 0 || clr != 0))
+           && (set != 0 || clr != 0 || (flags & MS_REMOUNT)))
                rc = mnt_context_append_hook(cxt, hs, MNT_STAGE_MOUNT, NULL,
                                        hook_set_vfsflags);
 
index e3b824e3bca6332ead40aefa2b255781a0715fb2..ede96e4354e641c499b365d23fdd18e9c1a2379f 100644 (file)
@@ -831,6 +831,7 @@ int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *cl
 {
        struct libmnt_iter itr;
        struct libmnt_opt *opt;
+       uint64_t remount_reset = 0;
 
        if (!ls || !ls->linux_map || !set || !clr)
                return -EINVAL;
@@ -838,6 +839,19 @@ int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *cl
        *set = 0, *clr = 0;
        mnt_reset_iter(&itr, MNT_ITER_FORWARD);
 
+       /* The classic mount(2) MS_REMOUNT resets all flags which are not
+        * specified (except atime stuff). For backward compatibility we need
+        * to emulate this semantic by mount_setattr(). The new
+        * mount_setattr() has simple set/unset sematinc and nothing is
+        * internally in kernel reseted.
+        */
+       if (mnt_optlist_is_remount(ls)
+           && !mnt_optlist_is_bind(ls)
+           && rec == MNT_OL_NOREC)
+               remount_reset = (MOUNT_ATTR_RDONLY| MOUNT_ATTR_NOSUID| \
+                                MOUNT_ATTR_NODEV | MOUNT_ATTR_NOEXEC| \
+                                MOUNT_ATTR_NOSYMFOLLOW);
+
        while (mnt_optlist_next_opt(ls, &itr, &opt) == 0) {
                uint64_t x = 0;
 
@@ -856,6 +870,9 @@ int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *cl
                if (flag_to_attr( opt->ent->id, &x) < 0)
                        continue;
 
+               if (x && remount_reset)
+                       remount_reset &= ~x;
+
                if (opt->ent->mask & MNT_INVERT) {
                        DBG(OPTLIST, ul_debugobj(ls, " clr: %s", opt->ent->name));
                        *clr |= x;
@@ -869,6 +886,9 @@ int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *cl
                }
        }
 
+       if (remount_reset)
+               *clr |= remount_reset;
+
        DBG(OPTLIST, ul_debugobj(ls, "return attrs set=0x%08" PRIx64
                                      ", clr=0x%08" PRIx64 " %s",
                                *set, *clr,