ext4: force revalidation of directory pointer after seekdir(2)
authorTheodore Ts'o <tytso@mit.edu>
Mon, 2 Apr 2018 03:21:03 +0000 (23:21 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 24 Apr 2018 07:42:59 +0000 (09:42 +0200)
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 <tytso@mit.edu>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ext4/dir.c

index da87cf757f7defc1050299f67257517c7b9e22a5..e2902d394f1badb78bd4c96cbb45d3814fb74265 100644 (file)
@@ -365,13 +365,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_peek_iversion(inode) - 1;
+       return ret;
 }
 
 /*