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

Reply via email to