From e800c3836e2c34aa32b6c46aba0b73cb2bb00f29 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 1 Apr 2018 23:21:03 -0400 Subject: [PATCH] ext4: force revalidation of directory pointer after seekdir(2) commit e40ff213898502d299351cc2fe1e350cd186f0d3 upstream. A malicious user could force the directory pointer to be in an invalid spot by using seekdir(2). Use the mechanism we already have to notice if the directory has changed since the last time we called ext4_readdir() to force a revalidation of the pointer. Reported-by: syzbot+1236ce66f79263e8a862@syzkaller.appspotmail.com Signed-off-by: Theodore Ts'o [bwh: Backported to 3.16: open-code inode_peek_iversion()] Signed-off-by: Ben Hutchings --- fs/ext4/dir.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index ef1bed66c14f..8dd5c51e2200 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -322,13 +322,15 @@ static loff_t ext4_dir_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; int dx_dir = is_dx_dir(inode); - loff_t htree_max = ext4_get_htree_eof(file); + loff_t ret, htree_max = ext4_get_htree_eof(file); if (likely(dx_dir)) - return generic_file_llseek_size(file, offset, whence, + ret = generic_file_llseek_size(file, offset, whence, htree_max, htree_max); else - return ext4_llseek(file, offset, whence); + ret = ext4_llseek(file, offset, whence); + file->f_version = inode->i_version - 1; + return ret; } /*