From patchwork Tue Mar 6 23:59:50 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: 145084 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 2B86DB6F9D for ; Wed, 7 Mar 2012 11:01:00 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1031577Ab2CGAA6 (ORCPT ); Tue, 6 Mar 2012 19:00:58 -0500 Received: from e6.ny.us.ibm.com ([32.97.182.146]:54309 "EHLO e6.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031282Ab2CGAA5 (ORCPT ); Tue, 6 Mar 2012 19:00:57 -0500 Received: from /spool/local by e6.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 6 Mar 2012 19:00:56 -0500 Received: from d01dlp02.pok.ibm.com (9.56.224.85) by e6.ny.us.ibm.com (192.168.1.106) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 6 Mar 2012 19:00:42 -0500 Received: from d01relay02.pok.ibm.com (d01relay02.pok.ibm.com [9.56.227.234]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 76C6F6E804F for ; Tue, 6 Mar 2012 19:00:39 -0500 (EST) Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay02.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q27000Ud362412 for ; Tue, 6 Mar 2012 19:00:00 -0500 Received: from d01av01.pok.ibm.com (loopback [127.0.0.1]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q275Umjr004827 for ; Wed, 7 Mar 2012 00:30:52 -0500 Received: from elm3b70.beaverton.ibm.com (elm3b70.beaverton.ibm.com [9.47.67.70]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q275UjkH004710; Wed, 7 Mar 2012 00:30:46 -0500 Subject: [PATCH 23/54] libext2fs: Add dx_root/dx_node checksum calculation and verification helpers 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 15:59:50 -0800 Message-ID: <20120306235950.11945.51872.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-1976-0000-0000-00000B3B3D2E Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Verify and calculate checksums of htree internal node blocks. Signed-off-by: Darrick J. Wong --- lib/ext2fs/csum.c | 149 +++++++++++++++++++++++++++++++++++++++++++++ lib/ext2fs/ext2_err.et.in | 3 + lib/ext2fs/ext2fs.h | 4 + 3 files changed, 156 insertions(+), 0 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/csum.c b/lib/ext2fs/csum.c index 8a0543c..8907459 100644 --- a/lib/ext2fs/csum.c +++ b/lib/ext2fs/csum.c @@ -30,6 +30,155 @@ #define STATIC static #endif +static __u16 do_nothing16(__u16 x) +{ + return x; +} + +static __u16 disk_to_host16(__u16 x) +{ + return ext2fs_le16_to_cpu(x); +} + +static errcode_t __get_dx_countlimit(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dx_countlimit **cc, + int *offset, + int need_swab) +{ + struct ext2_dir_entry *dp; + struct ext2_dx_root_info *root; + struct ext2_dx_countlimit *c; + int count_offset, max_sane_entries; + unsigned int rec_len; + __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16); + + rec_len = translate(dirent->rec_len); + + if (rec_len == fs->blocksize && translate(dirent->name_len) == 0) + count_offset = 8; + else if (rec_len == 12) { + dp = (struct ext2_dir_entry *)(((void *)dirent) + rec_len); + rec_len = translate(dp->rec_len); + if (rec_len != fs->blocksize - 12) + return EXT2_ET_DB_NOT_FOUND; + root = (struct ext2_dx_root_info *)(((void *)dp + 12)); + if (root->reserved_zero || + root->info_length != sizeof(struct ext2_dx_root_info)) + return EXT2_ET_DB_NOT_FOUND; + count_offset = 32; + } else + return EXT2_ET_DB_NOT_FOUND; + + c = (struct ext2_dx_countlimit *)(((void *)dirent) + count_offset); + max_sane_entries = (fs->blocksize - count_offset) / + sizeof(struct ext2_dx_entry); + if (ext2fs_le16_to_cpu(c->limit) > max_sane_entries || + ext2fs_le16_to_cpu(c->count) > max_sane_entries) + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; + + if (offset) + *offset = count_offset; + if (cc) + *cc = c; + + return 0; +} + +errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dx_countlimit **cc, + int *offset) +{ + return __get_dx_countlimit(fs, dirent, cc, offset, 0); +} + +static errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent, + __u32 *crc, int count_offset, int count, + struct ext2_dx_tail *t) +{ + errcode_t retval; + char *buf = (char *)dirent; + int size; + __u32 old_csum, gen; + struct ext2_inode inode; + + size = count_offset + (count * sizeof(struct ext2_dx_entry)); + old_csum = t->dt_checksum; + t->dt_checksum = 0; + + retval = ext2fs_read_inode(fs, inum, &inode); + if (retval) + return retval; + + inum = ext2fs_cpu_to_le32(inum); + gen = ext2fs_cpu_to_le32(inode.i_generation); + *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, + sizeof(inum)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); + *crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, + sizeof(struct ext2_dx_tail)); + t->dt_checksum = old_csum; + + return 0; +} + +static int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + __u32 calculated; + errcode_t retval; + struct ext2_dx_countlimit *c; + struct ext2_dx_tail *t; + int count_offset, limit, count; + + retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); + if (retval) + return 1; + limit = ext2fs_le16_to_cpu(c->limit); + count = ext2fs_le16_to_cpu(c->count); + if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > + fs->blocksize - sizeof(struct ext2_dx_tail)) + return 0; + /* htree structs are accessed in LE order */ + t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); + retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, count_offset, + count, t); + if (retval) + return 0; + + return ext2fs_le32_to_cpu(t->dt_checksum) == calculated; +} + +static errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum, + struct ext2_dir_entry *dirent) +{ + __u32 crc; + errcode_t retval = 0; + struct ext2_dx_countlimit *c; + struct ext2_dx_tail *t; + int count_offset, limit, count; + + retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); + if (retval) + return retval; + limit = ext2fs_le16_to_cpu(c->limit); + count = ext2fs_le16_to_cpu(c->count); + if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > + fs->blocksize - sizeof(struct ext2_dx_tail)) + return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; + t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); + + /* htree structs are accessed in LE order */ + retval = ext2fs_dx_csum(fs, inum, dirent, &crc, count_offset, count, t); + if (retval) + return retval; + t->dt_checksum = ext2fs_cpu_to_le32(crc); + return retval; +} + #define EXT3_EXTENT_TAIL_OFFSET(hdr) (sizeof(struct ext3_extent_header) + \ (sizeof(struct ext3_extent) * ext2fs_le16_to_cpu((hdr)->eh_max))) diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in index 9019026..1e51384 100644 --- a/lib/ext2fs/ext2_err.et.in +++ b/lib/ext2fs/ext2_err.et.in @@ -452,4 +452,7 @@ ec EXT2_ET_INODE_BITMAP_CSUM_INVALID, ec EXT2_ET_EXTENT_CSUM_INVALID, "Extent block checksum does not match extent block" +ec EXT2_ET_DIR_NO_SPACE_FOR_CSUM, + "Directory block does not have space for checksum" + end diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 8dd038a..e224e74 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_get_dx_countlimit(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dx_countlimit **cc, + int *offset); extern errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum, struct ext3_extent_header *eh);