]> git.baikalelectronics.ru Git - kernel.git/commit
ext4: fix potential infinite loop in ext4_dx_readdir()
authoryangerkun <yangerkun@huawei.com>
Tue, 14 Sep 2021 11:14:15 +0000 (19:14 +0800)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 1 Oct 2021 04:05:09 +0000 (00:05 -0400)
commit4a25206f0628d28aeeef81362c64c5b651b4a69f
treeeec6be15b2eabb5b26e87f27ef9fb629965d113d
parent8290ea2f2facc1896b15abaece45c928848725dd
ext4: fix potential infinite loop in ext4_dx_readdir()

When ext4_htree_fill_tree() fails, ext4_dx_readdir() can run into an
infinite loop since if info->last_pos != ctx->pos this will reset the
directory scan and reread the failing entry.  For example:

1. a dx_dir which has 3 block, block 0 as dx_root block, block 1/2 as
   leaf block which own the ext4_dir_entry_2
2. block 1 read ok and call_filldir which will fill the dirent and update
   the ctx->pos
3. block 2 read fail, but we has already fill some dirent, so we will
   return back to userspace will a positive return val(see ksys_getdents64)
4. the second ext4_dx_readdir will reset the world since info->last_pos
   != ctx->pos, and will also init the curr_hash which pos to block 1
5. So we will read block1 too, and once block2 still read fail, we can
   only fill one dirent because the hash of the entry in block1(besides
   the last one) won't greater than curr_hash
6. this time, we forget update last_pos too since the read for block2
   will fail, and since we has got the one entry, ksys_getdents64 can
   return success
7. Latter we will trapped in a loop with step 4~6

Cc: stable@kernel.org
Signed-off-by: yangerkun <yangerkun@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Link: https://lore.kernel.org/r/20210914111415.3921954-1-yangerkun@huawei.com
fs/ext4/dir.c