From: Ana Bobillo <[email protected]>

In the triple indirect branch, read_allocated_block() reads the third
level block from ext4fs_indir2_block[(rblock / perblock_child) %
(blksz / 4)] and records it in ext4fs_indir3_blkno, but it decides
whether that cached block can be reused by comparing against
ext4fs_indir2_block[rblock / perblock_child], without the modulo.

For a file block reached through the second or a later entry of the
triple indirect block (rblock >= (blksz / 4) * (blksz / 4)),
rblock / perblock_child is at least blksz / 4, so the compare reads
past the end of the blksz-byte ext4fs_indir2_block buffer and can
make the lookup reuse the wrong cached block.

Use the same index for the compare as for the read.

Signed-off-by: Ana Bobillo <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
---
(no changes since v1)

 fs/ext4/ext4_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 3aab1c87233..cff112fb99b 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -2008,9 +2008,9 @@ long int read_allocated_block(struct ext2_inode *inode, 
int fileblock,
                        }
                        ext4fs_indir3_size = blksz;
                }
-               if ((le32_to_cpu(ext4fs_indir2_block[rblock
-                                                      /
-                                                      perblock_child]) <<
+               if ((le32_to_cpu(ext4fs_indir2_block[(rblock /
+                                                     perblock_child) %
+                                                    (blksz / 4)]) <<
                     log2_blksz) != ext4fs_indir3_blkno) {
                        status =
                            ext4fs_devread((lbaint_t)le32_to_cpu

Reply via email to