mirror of https://github.com/vitalif/e2fsprogs
libext2fs: don't cache inodes that fail checksum verification
If an inode fails checksum verification, don't stuff a copy of it in the inode cache, because this can cause the library to fail to return the "corrupt inode" error code. In general, this happens if ext2fs_read_inode_full() is called twice on an inode with an incorrect checksum. If fs->flags has EXT2_FLAG_IGNORE_CSUM_ERRORS set during the first call and *unset* during the second call, the cache hit during the second call fails to return EXT2_ET_INODE_CSUM_INVALID as you'd expect. This happens during fsck because the first read_inode call happens as part of check_blocks and the second call happens during inode checksum revalidation. A file system with a slightly corrupt non-extent inode will trigger this. While we're at it, make the inode read function consistent with the rest of libext2fs -- copy the metadata object into the caller's buffer even if it fails checksum verification. This will help e2fsck avoid a double re-read later on down the line. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>crypto
parent
2e9d839156
commit
b9f95911e9
|
@ -709,7 +709,7 @@ errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
|||
io_channel io;
|
||||
int length = EXT2_INODE_SIZE(fs->super);
|
||||
struct ext2_inode_large *iptr;
|
||||
int cache_slot;
|
||||
int cache_slot, fail_csum;
|
||||
|
||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||
|
||||
|
@ -787,9 +787,7 @@ errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
|||
length = EXT2_INODE_SIZE(fs->super);
|
||||
|
||||
/* Verify the inode checksum. */
|
||||
if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
|
||||
!ext2fs_inode_csum_verify(fs, ino, iptr))
|
||||
return EXT2_ET_INODE_CSUM_INVALID;
|
||||
fail_csum = !ext2fs_inode_csum_verify(fs, ino, iptr);
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) iptr,
|
||||
|
@ -798,10 +796,15 @@ errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
|||
#endif
|
||||
|
||||
/* Update the inode cache bookkeeping */
|
||||
fs->icache->cache_last = cache_slot;
|
||||
fs->icache->cache[cache_slot].ino = ino;
|
||||
if (!fail_csum) {
|
||||
fs->icache->cache_last = cache_slot;
|
||||
fs->icache->cache[cache_slot].ino = ino;
|
||||
}
|
||||
memcpy(inode, iptr, (bufsize > length) ? length : bufsize);
|
||||
|
||||
if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && fail_csum)
|
||||
return EXT2_ET_INODE_CSUM_INVALID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
Pass 1: Checking inodes, blocks, and sizes
|
||||
Inode 12 passes checks, but checksum does not match inode. Fix? yes
|
||||
|
||||
Pass 2: Checking directory structure
|
||||
Pass 3: Checking directory connectivity
|
||||
Pass 4: Checking reference counts
|
||||
Pass 5: Checking group summary information
|
||||
|
||||
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
||||
test_filesys: 12/128 files (0.0% non-contiguous), 19/512 blocks
|
||||
Exit status is 1
|
|
@ -0,0 +1,7 @@
|
|||
Pass 1: Checking inodes, blocks, and sizes
|
||||
Pass 2: Checking directory structure
|
||||
Pass 3: Checking directory connectivity
|
||||
Pass 4: Checking reference counts
|
||||
Pass 5: Checking group summary information
|
||||
test_filesys: 12/128 files (0.0% non-contiguous), 19/512 blocks
|
||||
Exit status is 0
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
don't cache inodes that fail checksum verification
|
Loading…
Reference in New Issue