[Devel] [PATCH RHEL7 COMMIT] ms/ext4: check for out-of-order index extents in ext4_valid_extent_entries()

Konstantin Khorenko khorenko at virtuozzo.com
Mon Jun 20 21:04:06 MSK 2022


The commit is pushed to "branch-rh7-3.10.0-1160.62.1.vz7.187.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.62.1.vz7.187.5
------>
commit f5bb3c64765c2860f44d58ad1e42c2b2ecbbf8a1
Author: Zhang Yi <yi.zhang at huawei.com>
Date:   Tue Jun 14 17:53:30 2022 +0300

    ms/ext4: check for out-of-order index extents in ext4_valid_extent_entries()
    
    After commit 5946d089379a ("ext4: check for overlapping extents in
    ext4_valid_extent_entries()"), we can check out the overlapping extent
    entry in leaf extent blocks. But the out-of-order extent entry in index
    extent blocks could also trigger bad things if the filesystem is
    inconsistent. So this patch add a check to figure out the out-of-order
    index extents and return error.
    
    Signed-off-by: Zhang Yi <yi.zhang at huawei.com>
    Reviewed-by: Theodore Ts'o <tytso at mit.edu>
    Link: https://lore.kernel.org/r/20210908120850.4012324-2-yi.zhang@huawei.com
    Signed-off-by: Theodore Ts'o <tytso at mit.edu>
    
    (cherry-picked from ms commit 8dd27fecede55e8a4e67eef2878040ecad0f0d33)
    Changes: In original patch ext4_valid_extent_entries() sets *pblk and in
      __ext4_ext_check
        ext4_valid_extent_entries
        ext4_error_inode_err
          __ext4_error_inode
            ext4_handle_error
              save_error_info
    the s_last_error_block is set to this block. In rebased patch we need to
    manually set s_last_error_block for index extents case same as we
    already do for leaf case.
    
    https://jira.sw.ru/browse/PSBM-139452
    Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 fs/ext4/extents.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index cb31585002ca..76a2f153fb72 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -399,7 +399,12 @@ static int ext4_valid_extent_entries(struct inode *inode,
 				struct ext4_extent_header *eh,
 				int depth)
 {
+	struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
 	unsigned short entries;
+	ext4_fsblk_t pblock = 0;
+	ext4_lblk_t lblock = 0;
+	ext4_lblk_t prev = 0;
+
 	if (eh->eh_entries == 0)
 		return 1;
 
@@ -408,34 +413,37 @@ static int ext4_valid_extent_entries(struct inode *inode,
 	if (depth == 0) {
 		/* leaf entries */
 		struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
-		struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
-		ext4_fsblk_t pblock = 0;
-		ext4_lblk_t lblock = 0;
-		ext4_lblk_t prev = 0;
-		int len = 0;
 		while (entries) {
 			if (!ext4_valid_extent(inode, ext))
 				return 0;
 
 			/* Check for overlapping extents */
 			lblock = le32_to_cpu(ext->ee_block);
-			len = ext4_ext_get_actual_len(ext);
 			if ((lblock <= prev) && prev) {
 				pblock = ext4_ext_pblock(ext);
 				es->s_last_error_block = cpu_to_le64(pblock);
 				return 0;
 			}
+			prev = lblock + ext4_ext_get_actual_len(ext) - 1;
 			ext++;
 			entries--;
-			prev = lblock + len - 1;
 		}
 	} else {
 		struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
 		while (entries) {
 			if (!ext4_valid_extent_idx(inode, ext_idx))
 				return 0;
+
+			/* Check for overlapping index extents */
+			lblock = le32_to_cpu(ext_idx->ei_block);
+			if ((lblock <= prev) && prev) {
+				pblock = ext4_idx_pblock(ext_idx);
+				es->s_last_error_block = cpu_to_le64(pblock);
+				return 0;
+			}
 			ext_idx++;
 			entries--;
+			prev = lblock;
 		}
 	}
 	return 1;


More information about the Devel mailing list