xfs
[Top] [All Lists]

Review: Fix use after free on forced shutdown

To: xfs-dev@xxxxxxx
Subject: Review: Fix use after free on forced shutdown
From: David Chinner <dgc@xxxxxxx>
Date: Tue, 19 Dec 2006 16:30:12 +1100
Cc: xfs@xxxxxxxxxxx
Sender: xfs-bounce@xxxxxxxxxxx
User-agent: Mutt/1.4.2.1i
As found earlier today trying to reproduce a different use
after free, a machine with CONFIG_SLAB_DEBUG will panic on
a forced shutdown if the inode has an assocaited item
in the AIL.

Trivial fix is to remove the item from the AIL before
freeing it.

Cheers,

Dave.
-- 
Dave Chinner
Principal Engineer
SGI Australian Software Group

---
 fs/xfs/xfs_inode.c |   22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

Index: 2.6.x-xfs-new/fs/xfs/xfs_inode.c
===================================================================
--- 2.6.x-xfs-new.orig/fs/xfs/xfs_inode.c       2006-12-12 15:40:58.000000000 
+1100
+++ 2.6.x-xfs-new/fs/xfs/xfs_inode.c    2006-12-19 15:44:09.675298719 +1100
@@ -2704,10 +2704,24 @@ xfs_idestroy(
        ktrace_free(ip->i_dir_trace);
 #endif
        if (ip->i_itemp) {
-               /* XXXdpd should be able to assert this but shutdown
-                * is leaving the AIL behind. */
-               ASSERT(((ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL) == 0) 
||
-                      XFS_FORCED_SHUTDOWN(ip->i_mount));
+               /*
+                * Only if we are shutting down the fs will we see an
+                * inode still in the AIL. If it is there, we should remove
+                * it to prevent a use-after-free from occurring.
+                */
+               xfs_mount_t     *mp = ip->i_mount;
+               xfs_log_item_t  *lip = &ip->i_itemp->ili_item;
+               int             s;
+
+               ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
+                                      XFS_FORCED_SHUTDOWN(ip->i_mount));
+               if (lip->li_flags & XFS_LI_IN_AIL) {
+                       AIL_LOCK(mp, s);
+                       if (lip->li_flags & XFS_LI_IN_AIL)
+                               xfs_trans_delete_ail(mp, lip, s);
+                       else
+                               AIL_UNLOCK(mp, s);
+               }
                xfs_inode_item_destroy(ip);
        }
        kmem_zone_free(xfs_inode_zone, ip);


<Prev in Thread] Current Thread [Next in Thread>