| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Sun, 1 Apr 2018 23:21:03 -0400 |
| Subject: 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 <tytso@mit.edu> |
| [bwh: Backported to 3.16: open-code inode_peek_iversion()] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/ext4/dir.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| --- a/fs/ext4/dir.c |
| +++ b/fs/ext4/dir.c |
| @@ -322,13 +322,15 @@ static loff_t ext4_dir_llseek(struct fil |
| { |
| 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; |
| } |
| |
| /* |