mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
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>
This commit is contained in:
parent
a6cb767e24
commit
705db3fd46
@ -69,15 +69,6 @@ xfs_inode_alloc(
|
||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||
ASSERT(completion_done(&ip->i_flush));
|
||||
|
||||
/*
|
||||
* initialise the VFS inode here to get failures
|
||||
* out of the way early.
|
||||
*/
|
||||
if (!inode_init_always(mp->m_super, VFS_I(ip))) {
|
||||
kmem_zone_free(xfs_inode_zone, ip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialise the xfs inode */
|
||||
ip->i_ino = ino;
|
||||
ip->i_mount = mp;
|
||||
@ -113,6 +104,20 @@ xfs_inode_alloc(
|
||||
#ifdef XFS_DIR2_TRACE
|
||||
ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
|
||||
#endif
|
||||
/*
|
||||
* Now initialise the VFS inode. We do this after the xfs_inode
|
||||
* initialisation as internal failures will result in ->destroy_inode
|
||||
* being called and that will pass down through the reclaim path and
|
||||
* free the XFS inode. This path requires the XFS inode to already be
|
||||
* initialised. Hence if this call fails, the xfs_inode has already
|
||||
* been freed and we should not reference it at all in the error
|
||||
* handling.
|
||||
*/
|
||||
if (!inode_init_always(mp->m_super, VFS_I(ip)))
|
||||
return NULL;
|
||||
|
||||
/* prevent anyone from using this yet */
|
||||
VFS_I(ip)->i_state = I_NEW|I_LOCK;
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user