From: Karel Zak Date: Thu, 23 Mar 2023 14:25:00 +0000 (+0100) Subject: libmount: fix MS_REMOUNT emulation by mount_setattr() X-Git-Tag: v2.39-rc2~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fee1ddebfc5b84d26add58eb00a304520207ed2e;p=thirdparty%2Futil-linux.git libmount: fix MS_REMOUNT emulation by mount_setattr() 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 --- diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index b535382b4d..39fc841d50 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -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); diff --git a/libmount/src/optlist.c b/libmount/src/optlist.c index e3b824e3bc..ede96e4354 100644 --- a/libmount/src/optlist.c +++ b/libmount/src/optlist.c @@ -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,