* [PATCH 3/4 v4] exfat: add boot region verification @ 2020-05-31 9:30 ` Tetsuhiro Kohada 2020-06-01 12:21 ` Sungjong Seo 0 siblings, 1 reply; 2+ messages in thread From: Tetsuhiro Kohada @ 2020-05-31 9:30 UTC (permalink / raw) To: kohada.t2 Cc: kohada.tetsuhiro, mori.takahiro, motai.hirotaka, Namjae Jeon, Sungjong Seo, linux-fsdevel, linux-kernel Add Boot-Regions verification specified in exFAT specification. Note that the checksum type is strongly related to the raw structure, so the'u32 'type is used to clarify the number of bits. Signed-off-by: Tetsuhiro Kohada <kohada.t2@gmail.com> --- Changes in v2: - rebase with patch 'optimize dir-cache' applied - just print a warning when invalid exboot-signature detected - print additional information when invalid boot-checksum detected Changes in v3: - based on '[PATCH 2/4 v3] exfat: separate the boot sector analysis' Changes in v4: - fix type of p_sig/p_chksum to __le32 fs/exfat/exfat_fs.h | 1 + fs/exfat/misc.c | 14 +++++++++++++ fs/exfat/super.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index 9673e2d31045..eebbe5a84b2b 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -514,6 +514,7 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, u8 *tz, __le16 *time, __le16 *date, u8 *time_cs); unsigned short exfat_calc_chksum_2byte(void *data, int len, unsigned short chksum, int type); +u32 exfat_calc_chksum32(void *data, int len, u32 chksum, int type); void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync); void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, unsigned int size, unsigned char flags); diff --git a/fs/exfat/misc.c b/fs/exfat/misc.c index ab7f88b1f6d3..b82d2dd5bd7c 100644 --- a/fs/exfat/misc.c +++ b/fs/exfat/misc.c @@ -151,6 +151,20 @@ unsigned short exfat_calc_chksum_2byte(void *data, int len, return chksum; } +u32 exfat_calc_chksum32(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 << 31) | (chksum >> 1)) + *c; + } + return chksum; +} + void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int sync) { set_bit(EXFAT_SB_DIRTY, &EXFAT_SB(sb)->s_state); diff --git a/fs/exfat/super.c b/fs/exfat/super.c index 6a1330be5a9a..405717e4e3ea 100644 --- a/fs/exfat/super.c +++ b/fs/exfat/super.c @@ -491,6 +491,50 @@ static int exfat_read_boot_sector(struct super_block *sb) return 0; } +static int exfat_verify_boot_region(struct super_block *sb) +{ + struct buffer_head *bh = NULL; + u32 chksum = 0; + __le32 *p_sig, *p_chksum; + int sn, i; + + /* read boot sector sub-regions */ + for (sn = 0; sn < 11; sn++) { + bh = sb_bread(sb, sn); + if (!bh) + return -EIO; + + if (sn != 0 && sn <= 8) { + /* extended boot sector sub-regions */ + p_sig = (__le32 *)&bh->b_data[sb->s_blocksize - 4]; + if (le32_to_cpu(*p_sig) != EXBOOT_SIGNATURE) + exfat_warn(sb, "Invalid exboot-signature(sector = %d): 0x%08x", + sn, le32_to_cpu(*p_sig)); + } + + chksum = exfat_calc_chksum32(bh->b_data, sb->s_blocksize, + chksum, sn ? CS_DEFAULT : CS_BOOT_SECTOR); + brelse(bh); + } + + /* boot checksum sub-regions */ + bh = sb_bread(sb, sn); + if (!bh) + return -EIO; + + for (i = 0; i < sb->s_blocksize; i += sizeof(u32)) { + p_chksum = (__le32 *)&bh->b_data[i]; + if (le32_to_cpu(*p_chksum) != chksum) { + exfat_err(sb, "Invalid boot checksum (boot checksum : 0x%08x, checksum : 0x%08x)", + le32_to_cpu(*p_chksum), chksum); + brelse(bh); + return -EINVAL; + } + } + brelse(bh); + return 0; +} + /* mount the file system volume */ static int __exfat_fill_super(struct super_block *sb) { @@ -503,6 +547,12 @@ static int __exfat_fill_super(struct super_block *sb) goto free_bh; } + ret = exfat_verify_boot_region(sb); + if (ret) { + exfat_err(sb, "invalid boot region"); + goto free_bh; + } + ret = exfat_create_upcase_table(sb); if (ret) { exfat_err(sb, "failed to load upcase table"); -- 2.25.1 ^ permalink raw reply related [flat|nested] 2+ messages in thread
* RE: [PATCH 3/4 v4] exfat: add boot region verification 2020-05-31 9:30 ` [PATCH 3/4 v4] exfat: add boot region verification Tetsuhiro Kohada @ 2020-06-01 12:21 ` Sungjong Seo 0 siblings, 0 replies; 2+ messages in thread From: Sungjong Seo @ 2020-06-01 12:21 UTC (permalink / raw) To: 'Tetsuhiro Kohada' Cc: kohada.tetsuhiro, mori.takahiro, motai.hirotaka, 'Namjae Jeon', linux-fsdevel, linux-kernel > Add Boot-Regions verification specified in exFAT specification. > Note that the checksum type is strongly related to the raw structure, so > the'u32 'type is used to clarify the number of bits. > > Signed-off-by: Tetsuhiro Kohada <kohada.t2@gmail.com> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> > --- > Changes in v2: > - rebase with patch 'optimize dir-cache' applied > - just print a warning when invalid exboot-signature detected > - print additional information when invalid boot-checksum detected > Changes in v3: > - based on '[PATCH 2/4 v3] exfat: separate the boot sector analysis' > Changes in v4: > - fix type of p_sig/p_chksum to __le32 > > fs/exfat/exfat_fs.h | 1 + > fs/exfat/misc.c | 14 +++++++++++++ > fs/exfat/super.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 65 insertions(+) > > diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index > 9673e2d31045..eebbe5a84b2b 100644 > --- a/fs/exfat/exfat_fs.h > +++ b/fs/exfat/exfat_fs.h > @@ -514,6 +514,7 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, > struct timespec64 *ts, > u8 *tz, __le16 *time, __le16 *date, u8 *time_cs); unsigned > short exfat_calc_chksum_2byte(void *data, int len, > unsigned short chksum, int type); > +u32 exfat_calc_chksum32(void *data, int len, u32 chksum, int type); > void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int > sync); void exfat_chain_set(struct exfat_chain *ec, unsigned int dir, > unsigned int size, unsigned char flags); diff --git > a/fs/exfat/misc.c b/fs/exfat/misc.c index ab7f88b1f6d3..b82d2dd5bd7c > 100644 > --- a/fs/exfat/misc.c > +++ b/fs/exfat/misc.c > @@ -151,6 +151,20 @@ unsigned short exfat_calc_chksum_2byte(void *data, > int len, > return chksum; > } > > +u32 exfat_calc_chksum32(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 << 31) | (chksum >> 1)) + *c; > + } > + return chksum; > +} > + > void exfat_update_bh(struct super_block *sb, struct buffer_head *bh, int > sync) { > set_bit(EXFAT_SB_DIRTY, &EXFAT_SB(sb)->s_state); diff --git > a/fs/exfat/super.c b/fs/exfat/super.c index 6a1330be5a9a..405717e4e3ea > 100644 > --- a/fs/exfat/super.c > +++ b/fs/exfat/super.c > @@ -491,6 +491,50 @@ static int exfat_read_boot_sector(struct super_block > *sb) > return 0; > } > > +static int exfat_verify_boot_region(struct super_block *sb) { > + struct buffer_head *bh = NULL; > + u32 chksum = 0; > + __le32 *p_sig, *p_chksum; > + int sn, i; > + > + /* read boot sector sub-regions */ > + for (sn = 0; sn < 11; sn++) { > + bh = sb_bread(sb, sn); > + if (!bh) > + return -EIO; > + > + if (sn != 0 && sn <= 8) { > + /* extended boot sector sub-regions */ > + p_sig = (__le32 *)&bh->b_data[sb->s_blocksize - 4]; > + if (le32_to_cpu(*p_sig) != EXBOOT_SIGNATURE) > + exfat_warn(sb, "Invalid exboot-signature(sector > = %d): 0x%08x", > + sn, le32_to_cpu(*p_sig)); > + } > + > + chksum = exfat_calc_chksum32(bh->b_data, sb->s_blocksize, > + chksum, sn ? CS_DEFAULT : CS_BOOT_SECTOR); > + brelse(bh); > + } > + > + /* boot checksum sub-regions */ > + bh = sb_bread(sb, sn); > + if (!bh) > + return -EIO; > + > + for (i = 0; i < sb->s_blocksize; i += sizeof(u32)) { > + p_chksum = (__le32 *)&bh->b_data[i]; > + if (le32_to_cpu(*p_chksum) != chksum) { > + exfat_err(sb, "Invalid boot checksum (boot checksum : > 0x%08x, checksum : 0x%08x)", > + le32_to_cpu(*p_chksum), chksum); > + brelse(bh); > + return -EINVAL; > + } > + } > + brelse(bh); > + return 0; > +} > + > /* mount the file system volume */ > static int __exfat_fill_super(struct super_block *sb) { @@ -503,6 > +547,12 @@ static int __exfat_fill_super(struct super_block *sb) > goto free_bh; > } > > + ret = exfat_verify_boot_region(sb); > + if (ret) { > + exfat_err(sb, "invalid boot region"); > + goto free_bh; > + } > + > ret = exfat_create_upcase_table(sb); > if (ret) { > exfat_err(sb, "failed to load upcase table"); > -- > 2.25.1 ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-06-01 12:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20200531093027epcas1p114ae71536b54ddf42882831cceb007c9@epcas1p1.samsung.com>
2020-05-31 9:30 ` [PATCH 3/4 v4] exfat: add boot region verification Tetsuhiro Kohada
2020-06-01 12:21 ` Sungjong Seo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).