Patch "fs: do not update freeing inode i_io_list" has been added to the 6.0-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    fs: do not update freeing inode i_io_list

to the 6.0-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     fs-do-not-update-freeing-inode-i_io_list.patch
and it can be found in the queue-6.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit f284857ad6013fb3bccf7bd5d78cfa4524ff5c35
Author: Svyatoslav Feldsherov <feldsherov@xxxxxxxxxx>
Date:   Tue Nov 15 20:20:01 2022 +0000

    fs: do not update freeing inode i_io_list
    
    [ Upstream commit 4e3c51f4e805291b057d12f5dda5aeb50a538dc4 ]
    
    After commit cbfecb927f42 ("fs: record I_DIRTY_TIME even if inode
    already has I_DIRTY_INODE") writeback_single_inode can push inode with
    I_DIRTY_TIME set to b_dirty_time list. In case of freeing inode with
    I_DIRTY_TIME set this can happen after deletion of inode from i_io_list
    at evict. Stack trace is following.
    
    evict
    fat_evict_inode
    fat_truncate_blocks
    fat_flush_inodes
    writeback_inode
    sync_inode_metadata(inode, sync=0)
    writeback_single_inode(inode, wbc) <- wbc->sync_mode == WB_SYNC_NONE
    
    This will lead to use after free in flusher thread.
    
    Similar issue can be triggered if writeback_single_inode in the
    stack trace update inode->i_io_list. Add explicit check to avoid it.
    
    Fixes: cbfecb927f42 ("fs: record I_DIRTY_TIME even if inode already has I_DIRTY_INODE")
    Reported-by: syzbot+6ba92bd00d5093f7e371@xxxxxxxxxxxxxxxxxxxxxxxxx
    Reviewed-by: Jan Kara <jack@xxxxxxx>
    Signed-off-by: Svyatoslav Feldsherov <feldsherov@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20221115202001.324188-1-feldsherov@xxxxxxxxxx
    Signed-off-by: Theodore Ts'o <tytso@xxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 443f83382b9b..9958d4020771 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1712,18 +1712,26 @@ static int writeback_single_inode(struct inode *inode,
 	wb = inode_to_wb_and_lock_list(inode);
 	spin_lock(&inode->i_lock);
 	/*
-	 * If the inode is now fully clean, then it can be safely removed from
-	 * its writeback list (if any).  Otherwise the flusher threads are
-	 * responsible for the writeback lists.
+	 * If the inode is freeing, its i_io_list shoudn't be updated
+	 * as it can be finally deleted at this moment.
 	 */
-	if (!(inode->i_state & I_DIRTY_ALL))
-		inode_cgwb_move_to_attached(inode, wb);
-	else if (!(inode->i_state & I_SYNC_QUEUED)) {
-		if ((inode->i_state & I_DIRTY))
-			redirty_tail_locked(inode, wb);
-		else if (inode->i_state & I_DIRTY_TIME) {
-			inode->dirtied_when = jiffies;
-			inode_io_list_move_locked(inode, wb, &wb->b_dirty_time);
+	if (!(inode->i_state & I_FREEING)) {
+		/*
+		 * If the inode is now fully clean, then it can be safely
+		 * removed from its writeback list (if any). Otherwise the
+		 * flusher threads are responsible for the writeback lists.
+		 */
+		if (!(inode->i_state & I_DIRTY_ALL))
+			inode_cgwb_move_to_attached(inode, wb);
+		else if (!(inode->i_state & I_SYNC_QUEUED)) {
+			if ((inode->i_state & I_DIRTY))
+				redirty_tail_locked(inode, wb);
+			else if (inode->i_state & I_DIRTY_TIME) {
+				inode->dirtied_when = jiffies;
+				inode_io_list_move_locked(inode,
+							  wb,
+							  &wb->b_dirty_time);
+			}
 		}
 	}
 



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux