]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
exfat: fix handling of damaged volume in exfat_create_upcase_table()
authorDavid Timber <dxdt@dev.snart.me>
Sat, 11 Apr 2026 23:32:51 +0000 (08:32 +0900)
committerNamjae Jeon <linkinjeon@kernel.org>
Mon, 15 Jun 2026 10:55:17 +0000 (19:55 +0900)
When the size of the upcase table is set to zero in the dentry for any
reason(e.g. corrupted media or misbehaving device), an integer overflow
causes the module to loop indefinitely.

If the size of the upcase table is read zero, do not attempt to load the
table. Instead, fallback to loading the default upcase table. If the
size of the upcase table is zero or no upcase table is found, raise
exfat_fs_error() to mark the volume read-only.

Signed-off-by: David Timber <dxdt@dev.snart.me>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
fs/exfat/nls.c

index 57db08a5271cf8c304a58fba37d67f8ceec9a9c7..055447edcf9a6917c3ebd4e372cec118c8d219e1 100644 (file)
@@ -769,13 +769,18 @@ int exfat_create_upcase_table(struct super_block *sb)
 
                        tbl_clu  = le32_to_cpu(ep->dentry.upcase.start_clu);
                        tbl_size = le64_to_cpu(ep->dentry.upcase.size);
-
-                       sector = exfat_cluster_to_sector(sbi, tbl_clu);
-                       num_sectors = ((tbl_size - 1) >> blksize_bits) + 1;
-                       ret = exfat_load_upcase_table(sb, sector, num_sectors,
-                               le32_to_cpu(ep->dentry.upcase.checksum));
-
+                       if (tbl_size) {
+                               sector = exfat_cluster_to_sector(sbi, tbl_clu);
+                               num_sectors = ((tbl_size - 1) >> blksize_bits) + 1;
+                               ret = exfat_load_upcase_table(sb, sector, num_sectors,
+                                       le32_to_cpu(ep->dentry.upcase.checksum));
+                       } else {
+                               exfat_fs_error(sb,
+                                              "bad upcase table size (0 bytes). Please run fsck");
+                               ret = -EINVAL;
+                       }
                        brelse(bh);
+
                        if (ret && ret != -EIO) {
                                /* free memory from exfat_load_upcase_table call */
                                exfat_free_upcase_table(sbi);
@@ -790,6 +795,8 @@ int exfat_create_upcase_table(struct super_block *sb)
                        return -EIO;
        }
 
+       exfat_fs_error(sb, "no upcase table entry. Please run fsck");
+
 load_default:
        /* load default upcase table */
        return exfat_load_default_upcase_table(sb);