From patchwork Wed Mar 7 00:00:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 145086 X-Patchwork-Delegate: tytso@mit.edu Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 9AA9BB6EF1 for ; Wed, 7 Mar 2012 11:01:13 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1031571Ab2CGABL (ORCPT ); Tue, 6 Mar 2012 19:01:11 -0500 Received: from e7.ny.us.ibm.com ([32.97.182.137]:45897 "EHLO e7.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031282Ab2CGABK (ORCPT ); Tue, 6 Mar 2012 19:01:10 -0500 Received: from /spool/local by e7.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 6 Mar 2012 19:01:09 -0500 Received: from d01dlp02.pok.ibm.com (9.56.224.85) by e7.ny.us.ibm.com (192.168.1.107) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 6 Mar 2012 19:01:01 -0500 Received: from d01relay03.pok.ibm.com (d01relay03.pok.ibm.com [9.56.227.235]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id BFE296E804A for ; Tue, 6 Mar 2012 19:01:00 -0500 (EST) Received: from d01av03.pok.ibm.com (d01av03.pok.ibm.com [9.56.224.217]) by d01relay03.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q270103a263220 for ; Tue, 6 Mar 2012 19:01:00 -0500 Received: from d01av03.pok.ibm.com (loopback [127.0.0.1]) by d01av03.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q2700va2023908 for ; Tue, 6 Mar 2012 21:01:00 -0300 Received: from elm3b70.beaverton.ibm.com (elm3b70.beaverton.ibm.com [9.47.67.70]) by d01av03.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q2700qLR023375; Tue, 6 Mar 2012 21:00:53 -0300 Subject: [PATCH 31/54] libext2fs: Calculate and verify superblock checksums To: Andreas Dilger , Theodore Tso , "Darrick J. Wong" From: "Darrick J. Wong" Cc: Sunil Mushran , Amir Goldstein , Andi Kleen , Mingming Cao , Joel Becker , linux-ext4@vger.kernel.org, Coly Li Date: Tue, 06 Mar 2012 16:00:49 -0800 Message-ID: <20120307000049.11945.88017.stgit@elm3b70.beaverton.ibm.com> In-Reply-To: <20120306235720.11945.30629.stgit@elm3b70.beaverton.ibm.com> References: <20120306235720.11945.30629.stgit@elm3b70.beaverton.ibm.com> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12030700-5806-0000-0000-000013343938 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Calculate and verify the superblock checksums. Each copy of the superblock records the number of the group it's in and the FS UUID, so we can simply checksum the whole block. Signed-off-by: Darrick J. Wong --- lib/ext2fs/closefs.c | 19 ++++++++++++------- lib/ext2fs/csum.c | 35 +++++++++++++++++++++++++++++++++++ lib/ext2fs/ext2_err.et.in | 3 +++ lib/ext2fs/ext2fs.h | 4 ++++ lib/ext2fs/openfs.c | 6 ++++++ 5 files changed, 60 insertions(+), 7 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c index 1867be3..a0e28ba 100644 --- a/lib/ext2fs/closefs.c +++ b/lib/ext2fs/closefs.c @@ -246,15 +246,19 @@ static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, blk_t group_block, struct ext2_super_block *super_shadow) { + errcode_t retval; dgrp_t sgrp = group; if (sgrp > ((1 << 16) - 1)) sgrp = (1 << 16) - 1; + + super_shadow->s_block_group_nr = sgrp; #ifdef WORDS_BIGENDIAN - super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); -#else - fs->super->s_block_group_nr = sgrp; + ext2fs_swap_super(super_shadow); #endif + retval = ext2fs_superblock_csum_set(fs, super_shadow); + if (retval) + return retval; return io_channel_write_blk64(fs->io, group_block, -SUPERBLOCK_SIZE, super_shadow); @@ -314,6 +318,7 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags) &group_shadow); if (retval) goto errout; + memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block)); memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize * fs->desc_blocks); @@ -334,10 +339,6 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags) */ fs->super->s_state &= ~EXT2_VALID_FS; fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; -#ifdef WORDS_BIGENDIAN - *super_shadow = *fs->super; - ext2fs_swap_super(super_shadow); -#endif /* * If this is an external journal device, don't write out the @@ -412,6 +413,10 @@ write_primary_superblock_only: ext2fs_swap_super(super_shadow); #endif + retval = ext2fs_superblock_csum_set(fs, super_shadow); + if (retval) + return retval; + if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) retval = io_channel_flush(fs->io); retval = write_primary_superblock(fs, super_shadow); diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c index 46f0cb5..4d01bcd 100644 --- a/lib/ext2fs/csum.c +++ b/lib/ext2fs/csum.c @@ -30,6 +30,41 @@ #define STATIC static #endif +static __u32 ext2fs_superblock_csum(ext2_filsys fs, struct ext2_super_block *sb) +{ + int offset = offsetof(struct ext2_super_block, s_checksum); + + return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset); +} + +int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb) +{ + __u32 calculated; + + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) + return 1; + + calculated = ext2fs_superblock_csum(fs, sb); + + return ext2fs_le32_to_cpu(sb->s_checksum) == calculated; +} + +errcode_t ext2fs_superblock_csum_set(ext2_filsys fs, + struct ext2_super_block *sb) +{ + __u32 crc; + + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) + return 0; + + crc = ext2fs_superblock_csum(fs, sb); + sb->s_checksum = ext2fs_cpu_to_le32(crc); + + return 0; +} + static errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs, ext2_ino_t inum, blk64_t block, struct ext2_ext_attr_header *hdr, diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in index 177a97f..0fab4e0 100644 --- a/lib/ext2fs/ext2_err.et.in +++ b/lib/ext2fs/ext2_err.et.in @@ -461,4 +461,7 @@ ec EXT2_ET_DIR_CSUM_INVALID, ec EXT2_ET_EXT_ATTR_CSUM_INVALID, "Extended attribute block checksum does not match block" +ec EXT2_ET_SB_CSUM_INVALID, + "Superblock checksum does not match superblock" + end diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 5684df5..3c52f4b 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -952,6 +952,10 @@ extern __u32 ext2fs_crc32c_be(__u32 crc, unsigned char const *p, size_t len); extern __u32 ext2fs_crc32c_le(__u32 crc, unsigned char const *p, size_t len); /* csum.c */ +extern errcode_t ext2fs_superblock_csum_set(ext2_filsys fs, + struct ext2_super_block *sb); +extern int ext2fs_superblock_csum_verify(ext2_filsys fs, + struct ext2_super_block *sb); extern errcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum, blk64_t block, struct ext2_ext_attr_header *hdr); diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index 10beb06..8b7e750 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -193,6 +193,12 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, if (fs->orig_super) memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE); + if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && + !ext2fs_superblock_csum_verify(fs, fs->super)) { + retval = EXT2_ET_SB_CSUM_INVALID; + goto cleanup; + } + #ifdef WORDS_BIGENDIAN fs->flags |= EXT2_FLAG_SWAP_BYTES; ext2fs_swap_super(fs->super);