From eb88b751745b5e6b39ddfa2196b5efa9a25535a9 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 14 Mar 2020 23:24:39 -0400 Subject: [PATCH] libext2fs: make ext2fs_dirent_has_tail() more strict Previously ext2fs_dirent_has_tail() would return true if the directory was corrupted. If the directory is corrupted, then by definition it doesn't have a valid checksum tail. (This fixes a big-endian failure on the master branch.) Signed-off-by: Theodore Ts'o --- lib/ext2fs/csum.c | 11 +++++++---- tests/f_dir_bad_csum/expect.1 | 8 +------- tests/f_rebuild_csum_rootdir/expect.1 | 3 --- tests/f_resize_inode_meta_bg/expect.1 | 9 ++++++--- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c index 9823613..a717258 100644 --- a/lib/ext2fs/csum.c +++ b/lib/ext2fs/csum.c @@ -267,13 +267,15 @@ static errcode_t __get_dirent_tail(ext2_filsys fs, top = EXT2_DIRENT_TAIL(dirent, fs->blocksize); rec_len = translate(d->rec_len); - while (rec_len && !(rec_len & 0x3)) { + while ((void *) d < top) { + if ((rec_len < 8) || (rec_len & 0x03)) + return EXT2_ET_DIR_CORRUPTED; d = (struct ext2_dir_entry *)(((char *)d) + rec_len); - if ((void *)d >= top) - break; rec_len = translate(d->rec_len); } + if ((void *)d > ((void *)dirent + fs->blocksize)) + return EXT2_ET_DIR_CORRUPTED; if (d != top) return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; @@ -290,7 +292,8 @@ static errcode_t __get_dirent_tail(ext2_filsys fs, int ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent) { - return __get_dirent_tail(fs, dirent, NULL, 0) == 0; + return __get_dirent_tail(fs, dirent, NULL, 0) != + EXT2_ET_DIR_NO_SPACE_FOR_CSUM; } static errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum, diff --git a/tests/f_dir_bad_csum/expect.1 b/tests/f_dir_bad_csum/expect.1 index 94e72da..2c684fe 100644 --- a/tests/f_dir_bad_csum/expect.1 +++ b/tests/f_dir_bad_csum/expect.1 @@ -9,21 +9,15 @@ Fix? yes Directory inode 14, block #0, offset 0: directory has no checksum. Fix? yes -Directory inode 15, block #0, offset 0: directory has no checksum. -Fix? yes - Directory inode 15, block #0, offset 1000: directory corrupted Salvage? yes -Directory inode 16, block #0, offset 0: directory has no checksum. +Entry '' in ??? (15) has rec_len of 0, should be 12. Fix? yes Directory inode 16, block #0, offset 12: directory corrupted Salvage? yes -Directory inode 17, block #0, offset 0: directory has no checksum. -Fix? yes - Directory inode 17, block #0, offset 0: directory corrupted Salvage? yes diff --git a/tests/f_rebuild_csum_rootdir/expect.1 b/tests/f_rebuild_csum_rootdir/expect.1 index 4df58f9..bab07e0 100644 --- a/tests/f_rebuild_csum_rootdir/expect.1 +++ b/tests/f_rebuild_csum_rootdir/expect.1 @@ -1,8 +1,5 @@ Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure -Directory inode 2, block #0, offset 0: directory has no checksum. -Fix? yes - Directory inode 2, block #0, offset 0: directory corrupted Salvage? yes diff --git a/tests/f_resize_inode_meta_bg/expect.1 b/tests/f_resize_inode_meta_bg/expect.1 index 12055fc..c733c18 100644 --- a/tests/f_resize_inode_meta_bg/expect.1 +++ b/tests/f_resize_inode_meta_bg/expect.1 @@ -5,9 +5,6 @@ Resize_inode not enabled, but the resize inode is non-zero. Clear? yes Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure -Directory inode 2, block #0, offset 0: directory has no checksum. -Fix? yes - First entry '' (inode=348) in directory inode 2 (???) should be '.' Fix? yes @@ -19,6 +16,9 @@ Setting filetype for entry '..' in ??? (2) to 2. Directory inode 2, block #0, offset 860: directory corrupted Salvage? yes +Entry '' in ??? (2) has rec_len of 0, should be 12. +Fix? yes + Directory inode 11, block #0, offset 0: directory corrupted Salvage? yes @@ -42,6 +42,9 @@ Clear? yes Directory inode 11, block #3, offset 864: directory corrupted Salvage? yes +Entry '' in ??? (11) has rec_len of 0, should be 12. +Fix? yes + Pass 3: Checking directory connectivity '..' in / (2) is (0), should be / (2). Fix? yes -- 1.8.3.1