| From cc2048caec312a9eaa45642ad4e39c3466f6f06a 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: [PATCH] fat: fix uninit-memory access for partial initialized inode |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/fat/inode.c b/fs/fat/inode.c |
| index 05689198f5af..c3de5c0c7e7b 100644 |
| --- a/fs/fat/inode.c |
| +++ b/fs/fat/inode.c |
| @@ -744,6 +744,13 @@ static struct inode *fat_alloc_inode(struct super_block *sb) |
| 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; |
| } |
| |
| @@ -1368,16 +1375,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, |
| 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); |
| @@ -1831,13 +1828,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, |
| 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); |
| -- |
| 2.7.4 |
| |