[PATCH] erofs-utils: mount: fix flag-clearing bug and missing error check in parse_flagopts
Hardik
hardikkumarpro0005 at gmail.com
Mon Mar 2 23:20:48 AEDT 2026
From: Yifan Zhao <yifan.yfzhao at foxmail.com>
The MS_* constants in glibc's <sys/mount.h> are defined as members of
an anonymous enum whose underlying type is unsigned int (because the
last member, MS_NOUSER, is initialised with '1U << 31'). Therefore
~MS_RDONLY, ~MS_NOSUID, etc. are unsigned int values that, when stored
into a 'long flags' field, undergo zero-extension, not sign-extension.
As a result every 'clearing' entry (rw, suid, dev, exec, async, atime,
diratime, norelatime, loud) produced a positive long, so the
opts[i].flags < 0 guard in erofsmount_parse_flagopts() was never true
and the corresponding flags were set rather than cleared.
Fix by casting the operand to long before applying bitwise-NOT,
ensuring the result is a negative long with the correct bit pattern.
Also add the missing return-value check for erofsmount_parse_flagopts()
in the '-o' option handler.
Reported-by: Robert Rose <robert.rose at mailbox.org>
Closes: https://github.com/NixOS/nixpkgs/issues/494653
Signed-off-By: Yifan Zhao <yifan.yfzhao at foxmail.com>
Reviewed-by: Gao Xiang <hsiangkao at linux.alibaba.com>
Link: https://lore.kernel.org/r/tencent_003DF0338EAB42F1573BC0CCFBEACE321E06@qq.com
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
mount/main.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/mount/main.c b/mount/main.c
index b04be5d..dbee2ec 100644
--- a/mount/main.c
+++ b/mount/main.c
@@ -203,15 +203,15 @@ static long erofsmount_parse_flagopts(char *s, long flags, char **more)
} opts[] = {
{"defaults", 0}, {"quiet", 0}, // NOPs
{"user", 0}, {"nouser", 0}, // checked in fstab, ignored in -o
- {"ro", MS_RDONLY}, {"rw", ~MS_RDONLY},
- {"nosuid", MS_NOSUID}, {"suid", ~MS_NOSUID},
- {"nodev", MS_NODEV}, {"dev", ~MS_NODEV},
- {"noexec", MS_NOEXEC}, {"exec", ~MS_NOEXEC},
- {"sync", MS_SYNCHRONOUS}, {"async", ~MS_SYNCHRONOUS},
- {"noatime", MS_NOATIME}, {"atime", ~MS_NOATIME},
- {"norelatime", ~MS_RELATIME}, {"relatime", MS_RELATIME},
- {"nodiratime", MS_NODIRATIME}, {"diratime", ~MS_NODIRATIME},
- {"loud", ~MS_SILENT},
+ {"ro", MS_RDONLY}, {"rw", ~(long)MS_RDONLY},
+ {"nosuid", MS_NOSUID}, {"suid", ~(long)MS_NOSUID},
+ {"nodev", MS_NODEV}, {"dev", ~(long)MS_NODEV},
+ {"noexec", MS_NOEXEC}, {"exec", ~(long)MS_NOEXEC},
+ {"sync", MS_SYNCHRONOUS}, {"async", ~(long)MS_SYNCHRONOUS},
+ {"noatime", MS_NOATIME}, {"atime", ~(long)MS_NOATIME},
+ {"norelatime", ~(long)MS_RELATIME}, {"relatime", MS_RELATIME},
+ {"nodiratime", MS_NODIRATIME}, {"diratime", ~(long)MS_NODIRATIME},
+ {"loud", ~(long)MS_SILENT},
{"remount", MS_REMOUNT}, {"move", MS_MOVE},
// mand dirsync rec iversion strictatime
};
@@ -281,6 +281,7 @@ static int erofsmount_parse_options(int argc, char **argv)
{0, 0, 0, 0},
};
char *dot;
+ long ret;
int opt;
int i;
@@ -305,9 +306,11 @@ static int erofsmount_parse_options(int argc, char **argv)
break;
case 'o':
mountcfg.full_options = optarg;
- mountcfg.flags =
- erofsmount_parse_flagopts(optarg, mountcfg.flags,
- &mountcfg.options);
+ ret = erofsmount_parse_flagopts(optarg, mountcfg.flags,
+ &mountcfg.options);
+ if (ret < 0)
+ return (int)ret;
+ mountcfg.flags = ret;
break;
case 't':
dot = strchr(optarg, '.');
--
2.53.0.windows.1
More information about the Linux-erofs
mailing list