diff --git a/fs/exfat/super.c b/fs/exfat/super.c index 83396fd265cda..651e32b1e1c76 100644 --- a/fs/exfat/super.c +++ b/fs/exfat/super.c @@ -409,6 +409,8 @@ static int exfat_calibrate_blocksize(struct super_block *sb, int logical_sect) } if (logical_sect > sb->s_blocksize) { + const unsigned long saved_bs = sb->s_blocksize; + brelse(sbi->boot_bh); sbi->boot_bh = NULL; @@ -423,6 +425,10 @@ static int exfat_calibrate_blocksize(struct super_block *sb, int logical_sect) sb->s_blocksize); return -EIO; } + + exfat_warn(sb, "blocksize calibrated from device logical block size(%lu) to volume sector size(%d)!\n" + "Other implementations may not be able to handle this volume.", + saved_bs, logical_sect); } return 0; } @@ -431,6 +437,7 @@ static int exfat_read_boot_sector(struct super_block *sb) { struct boot_sector *p_boot; struct exfat_sb_info *sbi = EXFAT_SB(sb); + unsigned int nb_clusters; /* set block size to read super block */ if (!sb_min_blocksize(sb, 512)) { @@ -501,8 +508,17 @@ static int exfat_read_boot_sector(struct super_block *sb) sbi->data_start_sector = le32_to_cpu(p_boot->clu_offset); sbi->num_sectors = le64_to_cpu(p_boot->vol_length); /* because the cluster index starts with 2 */ - sbi->num_clusters = le32_to_cpu(p_boot->clu_count) + - EXFAT_RESERVED_CLUSTERS; + nb_clusters = le32_to_cpu(p_boot->clu_count); + /* + * The inclusive comparison in the following check seems a bit off(quite + * literally), but the exFAT format section 3.1.9 says + * "lesser of the following". Aye, aye, captain. + */ + if (nb_clusters >= EXFAT_MAX_NUM_CLUSTER) { + exfat_err(sb, "bogus number of clusters : %u", nb_clusters); + return -EINVAL; + } + sbi->num_clusters = nb_clusters + EXFAT_RESERVED_CLUSTERS; sbi->root_dir = le32_to_cpu(p_boot->root_cluster); sbi->dentries_per_clu = 1 << @@ -586,6 +602,34 @@ static int exfat_verify_boot_region(struct super_block *sb) return 0; } +static inline int exfat_check_volume_sizes(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + /* last sector of exFAT volume == end of last cluster */ + const sector_t lc_end = exfat_cluster_to_sector(sbi, sbi->num_clusters); + /* + * Do the calculations in bytes because the blocksize may have been + * calibrated in exfat_calibrate_blocksize(), and bdev_nr_sectors() + * always reports in 512-byte units. + */ + const unsigned long long vol_size = EXFAT_BLK_TO_B(sbi->num_sectors, sb); + const unsigned long long bdev_size = (unsigned long long)bdev_nr_bytes(sb->s_bdev); + + if (sbi->num_sectors < (unsigned long long)lc_end) { + exfat_err(sb, "number of clusters out of volume length bounds : num_sectors=%llu, last_cluster_sector=%lld", + sbi->num_sectors, lc_end); + return -EINVAL; + } + + if (bdev_size < vol_size) { + exfat_err(sb, "volume length out of bounds : dev=%llu, vol=%lld", + bdev_size, vol_size); + return -EINVAL; + } + + return 0; +} + /* mount the file system volume */ static int __exfat_fill_super(struct super_block *sb, struct exfat_chain *root_clu) @@ -605,6 +649,12 @@ static int __exfat_fill_super(struct super_block *sb, goto free_bh; } + ret = exfat_check_volume_sizes(sb); + if (ret) { + exfat_warn(sb, "volume bounds check failed. Please run fsck"); + goto free_bh; + } + /* * Call exfat_count_num_cluster() before searching for up-case and * bitmap directory entries to avoid infinite loop if they are missing @@ -652,6 +702,7 @@ static int __exfat_fill_super(struct super_block *sb, exfat_free_bitmap(sbi); free_bh: brelse(sbi->boot_bh); + exfat_free_upcase_table(sbi); return ret; } @@ -747,6 +798,7 @@ static int exfat_get_tree(struct fs_context *fc) static void exfat_free_sbi(struct exfat_sb_info *sbi) { + exfat_free_upcase_table(sbi); exfat_free_iocharset(sbi); kfree(sbi); }