dx_countlimit's count field was read from disk and used directly to compute the checksummed range (count_offset + count * sizeof(dx_entry)) without ever being checked against limit -- only limit itself was bounds-checked against the block size. A corrupted or maliciously crafted filesystem image that sets count to a large value (e.g. 65535) makes ext4_chksum() read far past the end of the directory block buffer, hitting adjacent slab objects. Reported-by: xiaowu.417@qq.com Signed-off-by: Artem Blagodarenko --- fs/ext4/namei.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index cc49ae04a6f6..a283e285937a 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -477,6 +477,10 @@ static int ext4_dx_csum_verify(struct inode *inode, warn_no_space_for_csum(inode); return 0; } + if (count > limit) { + EXT4_ERROR_INODE(inode, "dir seems corrupt? Run e2fsck -D."); + return 0; + } t = (struct dx_tail *)(((struct dx_entry *)c) + limit); if (t->dt_checksum != ext4_dx_csum(inode, dirent, count_offset, @@ -506,6 +510,10 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent) warn_no_space_for_csum(inode); return; } + if (count > limit) { + EXT4_ERROR_INODE(inode, "dir seems corrupt? Run e2fsck -D."); + return; + } t = (struct dx_tail *)(((struct dx_entry *)c) + limit); t->dt_checksum = ext4_dx_csum(inode, dirent, count_offset, count, t); -- 2.43.7