From b47820edd1634dc1208f9212b7ecfb4230610a23 Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Sun, 3 Jul 2016 17:51:39 -0400 Subject: ext4: avoid modifying checksum fields directly during checksum verification We temporally change checksum fields in buffers of some types of metadata into '0' for verifying the checksum values. By doing this without locking the buffer, some metadata's checksums, which are being committed or written back to the storage, could be damaged. In our test, several metadata blocks were found with damaged metadata checksum value during recovery process. When we only verify the checksum value, we have to avoid modifying checksum fields directly. Signed-off-by: Daeho Jeong Signed-off-by: Youngjin Gil Signed-off-by: Theodore Ts'o Reviewed-by: Darrick J. Wong --- fs/ext4/xattr.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'fs/ext4/xattr.c') diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e79bd32b9b79..39e9cfb1b371 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -121,17 +121,18 @@ static __le32 ext4_xattr_block_csum(struct inode *inode, { struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); __u32 csum; - __le32 save_csum; __le64 dsk_block_nr = cpu_to_le64(block_nr); + __u32 dummy_csum = 0; + int offset = offsetof(struct ext4_xattr_header, h_checksum); - save_csum = hdr->h_checksum; - hdr->h_checksum = 0; csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&dsk_block_nr, sizeof(dsk_block_nr)); - csum = ext4_chksum(sbi, csum, (__u8 *)hdr, - EXT4_BLOCK_SIZE(inode->i_sb)); + csum = ext4_chksum(sbi, csum, (__u8 *)hdr, offset); + csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum)); + offset += sizeof(dummy_csum); + csum = ext4_chksum(sbi, csum, (__u8 *)hdr + offset, + EXT4_BLOCK_SIZE(inode->i_sb) - offset); - hdr->h_checksum = save_csum; return cpu_to_le32(csum); } -- cgit v1.2.3