[PATCH] fs/unicode: Properly reject invalid encoding version strings

Gabriel Krisman Bertazi <[email protected]> Fri, 31 Jul 2026 16:20:45 -0400
Newsgroups org.kernel.vger.linux-fsdevel
Message-ID <[email protected]>
Casefolding filesystems can request a specific version of UTF-8 at
mount-time.  utf8_parse_version then assembles the "major.minor.rev"
string into an unsigned int.  There were two issues with the parser
logic: first, individual fields are read as signed int, allowing
negative numbers, second, an overflowed field will result in unexpected
results. Something like the below actually succeeds to mount using
utf8-12.1.0.

 mount -t tmpfs -o casefold=utf8-12.0.256 none /mnt
[   10.867859] tmpfs: Using encoding : utf8-12.1.0

Signed-off-by: Gabriel Krisman Bertazi <[email protected]>
---
 fs/unicode/utf8-core.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c
index 543c60c12461..c0a41b712e42 100644
--- a/fs/unicode/utf8-core.c
+++ b/fs/unicode/utf8-core.c
@@ -226,17 +226,19 @@ int utf8_parse_version(char *version)
 	substring_t args[3];
 	unsigned int maj, min, rev;
 	static const struct match_token token[] = {
-		{1, "%d.%d.%d"},
+		{1, "%u.%u.%u"},
 		{0, NULL}
 	};
 
 	if (match_token(version, token, args) != 1)
 		return -EINVAL;
 
-	if (match_int(&args[0], &maj) || match_int(&args[1], &min) ||
-	    match_int(&args[2], &rev))
+	if (match_uint(&args[0], &maj) || match_uint(&args[1], &min) ||
+	    match_uint(&args[2], &rev))
 		return -EINVAL;
 
+	if (maj > U8_MAX || min > U8_MAX || rev > U8_MAX)
+		return -EINVAL;
 	return UNICODE_AGE(maj, min, rev);
 }
 EXPORT_SYMBOL(utf8_parse_version);
-- 
2.55.0