From patchwork Tue Feb 28 13:56:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Theodore Ts'o X-Patchwork-Id: 733575 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 3vXh3P6M3nz9s7m for ; Wed, 1 Mar 2017 01:36:33 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=thunk.org header.i=@thunk.org header.b="ZIQBuRcq"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752415AbdB1Ogd (ORCPT ); Tue, 28 Feb 2017 09:36:33 -0500 Received: from imap.thunk.org ([74.207.234.97]:41960 "EHLO imap.thunk.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752402AbdB1Ogc (ORCPT ); Tue, 28 Feb 2017 09:36:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=thunk.org; s=ef5046eb; h=Message-Id:Date:Subject:Cc:To:From; bh=W2tatyU8H6Og86JEoXUTWTXO69ADb9z2u8e+pjxFAxA=; b=ZIQBuRcqyrrlz9V2A4TpsXy9p2RazEYK5mDGh8hvtfAMDrDxC00fHUI4beev/oLluSKpDaauwm8ALDXVdIB/JS/SG47Qwz/28xuYYK0AxcadLFLTaGtviChdgtlNLbiTU5691nV3bVNeywueyFmUCHM/f4MKzU7nxOYSIA/8eGA=; Received: from root (helo=callcc.thunk.org) by imap.thunk.org with local-esmtp (Exim 4.84_2) (envelope-from ) id 1ciiHz-0003nd-HH; Tue, 28 Feb 2017 13:58:03 +0000 Received: by callcc.thunk.org (Postfix, from userid 15806) id 2A447C002B1; Tue, 28 Feb 2017 08:56:57 -0500 (EST) From: Theodore Ts'o To: Ext4 Developers List Cc: Theodore Ts'o Subject: [PATCH] ext4: lock the the xattr block before calculating its checksum Date: Tue, 28 Feb 2017 08:56:50 -0500 Message-Id: <20170228135650.28045-1-tytso@mit.edu> X-Mailer: git-send-email 2.11.0.rc0.7.gbe5a750 X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: tytso@thunk.org X-SA-Exim-Scanned: No (on imap.thunk.org); SAEximRunCond expanded to false Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org We must lock the xattr block in order to avoid spurious checksum failures. https://bugzilla.kernel.org/show_bug.cgi?id=193661 Reported-by: Colin Ian King Signed-off-by: Theodore Ts'o Reviewed-by: Darrick J. Wong --- fs/ext4/xattr.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 67636acf7624..3247057ef5ff 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -131,30 +131,27 @@ static __le32 ext4_xattr_block_csum(struct inode *inode, } static int ext4_xattr_block_csum_verify(struct inode *inode, - sector_t block_nr, - struct ext4_xattr_header *hdr) + struct buffer_head *bh) { - if (ext4_has_metadata_csum(inode->i_sb) && - (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr))) - return 0; - return 1; -} - -static void ext4_xattr_block_csum_set(struct inode *inode, - sector_t block_nr, - struct ext4_xattr_header *hdr) -{ - if (!ext4_has_metadata_csum(inode->i_sb)) - return; + struct ext4_xattr_header *hdr = BHDR(bh); + int ret = 1; - hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr); + if (ext4_has_metadata_csum(inode->i_sb)) { + lock_buffer(bh); + ret = hdr->h_checksum == ext4_xattr_block_csum(inode, + bh->b_blocknr, hdr); + unlock_buffer(bh); + } + return ret; } static inline int ext4_handle_dirty_xattr_block(handle_t *handle, struct inode *inode, struct buffer_head *bh) { - ext4_xattr_block_csum_set(inode, bh->b_blocknr, BHDR(bh)); + if (ext4_has_metadata_csum(inode->i_sb)) + BHDR(bh)->h_checksum = ext4_xattr_block_csum(inode, + bh->b_blocknr, BHDR(bh)); return ext4_handle_dirty_metadata(handle, inode, bh); } @@ -233,7 +230,7 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || BHDR(bh)->h_blocks != cpu_to_le32(1)) return -EFSCORRUPTED; - if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) + if (!ext4_xattr_block_csum_verify(inode, bh)) return -EFSBADCRC; error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, bh->b_data);