Add Boot-Regions verification specified in exFAT specification. Reviewed-by: Takahiro Mori <mori.takah...@ab.mitsubishielectric.co.jp> Signed-off-by: Tetsuhiro Kohada <kohada.tetsuh...@dc.mitsubishielectric.co.jp> --- drivers/staging/exfat/exfat_core.c | 69 ++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 3faa7f35c77c..07c876bb1759 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -2017,7 +2017,20 @@ u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type) chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + (u16)*c; } + return chksum; +} +u32 calc_checksum32(void *data, int len, u32 chksum, int type) +{ + int i; + u8 *c = (u8 *)data; + + for (i = 0; i < len; i++, c++) { + if (unlikely(type == CS_BOOT_SECTOR && + (i == 106 || i == 107 || i == 112))) + continue; + chksum = ((chksum & 1) << 31 | chksum >> 1) + (u32)*c; + } return chksum; } @@ -2053,6 +2066,58 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, return 0; } +static int verify_boot_region(struct super_block *sb) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct buffer_head *tmp_bh = NULL; + u32 chksum = 0, *p_signatue, *p_chksum; + int sn = 0, i, ret; + + /* read boot sector sub-regions */ + ret = sector_read(sb, sn++, &tmp_bh, 1); + if (ret) + goto out; + + chksum = calc_checksum32(tmp_bh->b_data, p_bd->sector_size, + chksum, CS_BOOT_SECTOR); + + while (sn < 11) { + ret = sector_read(sb, sn++, &tmp_bh, 1); + if (ret) + goto out; + + chksum = calc_checksum32(tmp_bh->b_data, p_bd->sector_size, + chksum, CS_DEFAULT); + + /* skip OEM Parameters & Reserved sub-regions */ + if (sn >= 9) + continue; + + /* extended boot sector sub-regions */ + p_signatue = (u32 *)(tmp_bh->b_data + p_bd->sector_size - 4); + if (le32_to_cpu(*p_signatue) != EXBOOT_SIGNATURE) { + ret = -EFSCORRUPTED; + goto out; + } + } + + /* boot checksum sub-regions */ + ret = sector_read(sb, sn++, &tmp_bh, 1); + if (ret) + goto out; + + p_chksum = (u32 *)tmp_bh->b_data; + for (i = 0; i < p_bd->sector_size / 4; i++) { + if (le32_to_cpu(*p_chksum) != chksum) { + ret = -EFSCORRUPTED; + goto out; + } + } +out: + brelse(tmp_bh); + return ret; +} + static int read_boot_sector(struct super_block *sb) { struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); @@ -2129,6 +2194,10 @@ s32 exfat_mount(struct super_block *sb) if (ret) goto err_out; + ret = verify_boot_region(sb); + if (ret) + goto err_out; + ret = load_alloc_bitmap(sb); if (ret) goto err_out; -- 2.25.1 _______________________________________________ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel