xfs: fix double free of inode

If we fail to initialise the VFS inode in inode_init_always(),
it will call ->delete_inode internally resulting in the inode being
freed. Hence we need to delay the call to inode_init_always()
until after the XFS inode is sufficient set up to handle a
call to ->delete_inode, and then if that fails do not touch
the inode again at all as it has been freed.

Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>

authored by

Dave Chinner and committed by
Christoph Hellwig
705db3fd a6cb767e

+14 -9
+14 -9
fs/xfs/xfs_iget.c
··· 69 69 ASSERT(!spin_is_locked(&ip->i_flags_lock)); 70 70 ASSERT(completion_done(&ip->i_flush)); 71 71 72 - /* 73 - * initialise the VFS inode here to get failures 74 - * out of the way early. 75 - */ 76 - if (!inode_init_always(mp->m_super, VFS_I(ip))) { 77 - kmem_zone_free(xfs_inode_zone, ip); 78 - return NULL; 79 - } 80 - 81 72 /* initialise the xfs inode */ 82 73 ip->i_ino = ino; 83 74 ip->i_mount = mp; ··· 104 113 #ifdef XFS_DIR2_TRACE 105 114 ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); 106 115 #endif 116 + /* 117 + * Now initialise the VFS inode. We do this after the xfs_inode 118 + * initialisation as internal failures will result in ->destroy_inode 119 + * being called and that will pass down through the reclaim path and 120 + * free the XFS inode. This path requires the XFS inode to already be 121 + * initialised. Hence if this call fails, the xfs_inode has already 122 + * been freed and we should not reference it at all in the error 123 + * handling. 124 + */ 125 + if (!inode_init_always(mp->m_super, VFS_I(ip))) 126 + return NULL; 127 + 128 + /* prevent anyone from using this yet */ 129 + VFS_I(ip)->i_state = I_NEW|I_LOCK; 107 130 108 131 return ip; 109 132 }