udf: Avoid accessing uninitialized data on failed inode read
authorJan Kara <jack@suse.cz>
Fri, 25 Sep 2020 10:14:03 +0000 (12:14 +0200)
committerJan Kara <jack@suse.cz>
Tue, 29 Sep 2020 15:21:46 +0000 (17:21 +0200)
When we fail to read inode, some data accessed in udf_evict_inode() may
be uninitialized. Move the accesses to !is_bad_inode() branch.

Reported-by: syzbot+91f02b28f9bb5f5f1341@syzkaller.appspotmail.com
Signed-off-by: Jan Kara <jack@suse.cz>
fs/udf/inode.c

index adaba8e..5661184 100644 (file)
@@ -139,21 +139,24 @@ void udf_evict_inode(struct inode *inode)
        struct udf_inode_info *iinfo = UDF_I(inode);
        int want_delete = 0;
 
-       if (!inode->i_nlink && !is_bad_inode(inode)) {
-               want_delete = 1;
-               udf_setsize(inode, 0);
-               udf_update_inode(inode, IS_SYNC(inode));
+       if (!is_bad_inode(inode)) {
+               if (!inode->i_nlink) {
+                       want_delete = 1;
+                       udf_setsize(inode, 0);
+                       udf_update_inode(inode, IS_SYNC(inode));
+               }
+               if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
+                   inode->i_size != iinfo->i_lenExtents) {
+                       udf_warn(inode->i_sb,
+                                "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n",
+                                inode->i_ino, inode->i_mode,
+                                (unsigned long long)inode->i_size,
+                                (unsigned long long)iinfo->i_lenExtents);
+               }
        }
        truncate_inode_pages_final(&inode->i_data);
        invalidate_inode_buffers(inode);
        clear_inode(inode);
-       if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
-           inode->i_size != iinfo->i_lenExtents) {
-               udf_warn(inode->i_sb, "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n",
-                        inode->i_ino, inode->i_mode,
-                        (unsigned long long)inode->i_size,
-                        (unsigned long long)iinfo->i_lenExtents);
-       }
        kfree(iinfo->i_ext.i_data);
        iinfo->i_ext.i_data = NULL;
        udf_clear_extent_cache(inode);