Just verify the remaining unknown on-disk data instead of allocating a
temporary buffer for the whole superblock and zeroing out the checksum
field since .magic(EROFS_SUPER_MAGIC_V1) is verified and .checksum(0)
is fixed.

Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com>
---
 fs/erofs/erofs_fs.h |  3 ++-
 fs/erofs/super.c    | 30 +++++++++++-------------------
 2 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h
index c8f2ae845bd2..199395ed1c1f 100644
--- a/fs/erofs/erofs_fs.h
+++ b/fs/erofs/erofs_fs.h
@@ -9,6 +9,7 @@
 #ifndef __EROFS_FS_H
 #define __EROFS_FS_H
 
+/* to allow for x86 boot sectors and other oddities. */
 #define EROFS_SUPER_OFFSET      1024
 
 #define EROFS_FEATURE_COMPAT_SB_CHKSUM          0x00000001
@@ -54,7 +55,7 @@ struct erofs_deviceslot {
 /* erofs on-disk super block (currently 128 bytes) */
 struct erofs_super_block {
        __le32 magic;           /* file system magic number */
-       __le32 checksum;        /* crc32c(super_block) */
+       __le32 checksum;        /* crc32c to avoid unexpected on-disk overlap */
        __le32 feature_compat;
        __u8 blkszbits;         /* filesystem block size in bit shift */
        __u8 sb_extslots;       /* superblock size = 128 + sb_extslots * 16 */
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 9166054370aa..faf1506c47f5 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -39,29 +39,21 @@ void _erofs_printk(struct super_block *sb, const char *fmt, 
...)
 
 static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
 {
-       size_t len = 1 << EROFS_SB(sb)->blkszbits;
-       struct erofs_super_block *dsb;
-       u32 expected_crc, crc;
+       struct erofs_super_block *dsb = sbdata + EROFS_SUPER_OFFSET;
+       u32 len = 1 << EROFS_SB(sb)->blkszbits, crc;
 
        if (len > EROFS_SUPER_OFFSET)
                len -= EROFS_SUPER_OFFSET;
+       len -= offsetof(struct erofs_super_block, checksum) +
+                       sizeof(dsb->checksum);
 
-       dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, len, GFP_KERNEL);
-       if (!dsb)
-               return -ENOMEM;
-
-       expected_crc = le32_to_cpu(dsb->checksum);
-       dsb->checksum = 0;
-       /* to allow for x86 boot sectors and other oddities. */
-       crc = crc32c(~0, dsb, len);
-       kfree(dsb);
-
-       if (crc != expected_crc) {
-               erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected",
-                         crc, expected_crc);
-               return -EBADMSG;
-       }
-       return 0;
+       /* skip .magic(pre-verified) and .checksum(0) fields */
+       crc = crc32c(0x5045B54A, (&dsb->checksum) + 1, len);
+       if (crc == le32_to_cpu(dsb->checksum))
+               return 0;
+       erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected",
+                 crc, le32_to_cpu(dsb->checksum));
+       return -EBADMSG;
 }
 
 static void erofs_inode_init_once(void *ptr)
-- 
2.43.5

Reply via email to