diff options
| author | David Timber <dxdt@dev.snart.me> | 2026-04-12 08:32:51 +0900 |
|---|---|---|
| committer | Namjae Jeon <linkinjeon@kernel.org> | 2026-06-15 19:55:17 +0900 |
| commit | 20dd3185d13865214ff25b0bf7b931e8d73be1ac (patch) | |
| tree | abe9d9b6488955db6a34cbe38994396396625759 /fs/exfat | |
| parent | 0e0611827f3349d0a2ac121c023a6d3260dcecdb (diff) | |
exfat: fix handling of damaged volume in exfat_create_upcase_table()
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>
Diffstat (limited to 'fs/exfat')
| -rw-r--r-- | fs/exfat/nls.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c index 57db08a5271c..055447edcf9a 100644 --- a/fs/exfat/nls.c +++ b/fs/exfat/nls.c @@ -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); |
