| From bc87302a093f0eab45cd4e250c2021299f712ec6 Mon Sep 17 00:00:00 2001 |
| From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> |
| Date: Thu, 5 Mar 2020 22:28:36 -0800 |
| Subject: fat: fix uninit-memory access for partial initialized inode |
| |
| From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> |
| |
| commit bc87302a093f0eab45cd4e250c2021299f712ec6 upstream. |
| |
| When get an error in the middle of reading an inode, some fields in the |
| inode might be still not initialized. And then the evict_inode path may |
| access those fields via iput(). |
| |
| To fix, this makes sure that inode fields are initialized. |
| |
| Reported-by: syzbot+9d82b8de2992579da5d0@syzkaller.appspotmail.com |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> |
| Cc: <stable@vger.kernel.org> |
| Link: http://lkml.kernel.org/r/871rqnreqx.fsf@mail.parknet.co.jp |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/fat/inode.c | 19 +++++++------------ |
| 1 file changed, 7 insertions(+), 12 deletions(-) |
| |
| --- a/fs/fat/inode.c |
| +++ b/fs/fat/inode.c |
| @@ -749,6 +749,13 @@ static struct inode *fat_alloc_inode(str |
| return NULL; |
| |
| init_rwsem(&ei->truncate_lock); |
| + /* Zeroing to allow iput() even if partial initialized inode. */ |
| + ei->mmu_private = 0; |
| + ei->i_start = 0; |
| + ei->i_logstart = 0; |
| + ei->i_attrs = 0; |
| + ei->i_pos = 0; |
| + |
| return &ei->vfs_inode; |
| } |
| |
| @@ -1373,16 +1380,6 @@ out: |
| return 0; |
| } |
| |
| -static void fat_dummy_inode_init(struct inode *inode) |
| -{ |
| - /* Initialize this dummy inode to work as no-op. */ |
| - MSDOS_I(inode)->mmu_private = 0; |
| - MSDOS_I(inode)->i_start = 0; |
| - MSDOS_I(inode)->i_logstart = 0; |
| - MSDOS_I(inode)->i_attrs = 0; |
| - MSDOS_I(inode)->i_pos = 0; |
| -} |
| - |
| static int fat_read_root(struct inode *inode) |
| { |
| struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
| @@ -1843,13 +1840,11 @@ int fat_fill_super(struct super_block *s |
| fat_inode = new_inode(sb); |
| if (!fat_inode) |
| goto out_fail; |
| - fat_dummy_inode_init(fat_inode); |
| sbi->fat_inode = fat_inode; |
| |
| fsinfo_inode = new_inode(sb); |
| if (!fsinfo_inode) |
| goto out_fail; |
| - fat_dummy_inode_init(fsinfo_inode); |
| fsinfo_inode->i_ino = MSDOS_FSINFO_INO; |
| sbi->fsinfo_inode = fsinfo_inode; |
| insert_inode_hash(fsinfo_inode); |