Btrfs: fix crash due to not cleaning up tree log block's dirty bits

"Linux Kernel Mailing List" <[email protected]> Fri, 16 Feb 2018 17:44:22 +0000 (UTC)
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/1846430c24d66e85cc58286b3319c82cd54debb2
Commit:     1846430c24d66e85cc58286b3319c82cd54debb2
Parent:     e89166990f11c3f21e1649d760dd35f9e410321c
Refname:    refs/heads/master
Author:     Liu Bo <[email protected]>
AuthorDate: Thu Jan 25 11:02:51 2018 -0700
Committer:  David Sterba <[email protected]>
CommitDate: Fri Feb 2 16:24:24 2018 +0100

    Btrfs: fix crash due to not cleaning up tree log block's dirty bits
    
    In cases that the whole fs flips into readonly status due to failures in
    critical sections, then log tree's blocks are still dirty, and this leads
    to a crash during umount time, the crash is about use-after-free,
    
    umount
     -> close_ctree
        -> stop workers
        -> iput(btree_inode)
           -> iput_final
              -> write_inode_now
                 -> ...
                   -> queue job on stop'd workers
    
    cc: <[email protected]> v3.12+
    Fixes: 681ae50917df ("Btrfs: cleanup reserved space when freeing tree log on error")
    Signed-off-by: Liu Bo <[email protected]>
    Reviewed-by: Josef Bacik <[email protected]>
    Signed-off-by: David Sterba <[email protected]>
---
 fs/btrfs/tree-log.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ee1aaed1330e..1920c2149f88 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2471,6 +2471,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
 					clean_tree_block(fs_info, next);
 					btrfs_wait_tree_block_writeback(next);
 					btrfs_tree_unlock(next);
+				} else {
+					if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
+						clear_extent_buffer_dirty(next);
 				}
 
 				WARN_ON(root_owner !=
@@ -2551,6 +2554,9 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
 					clean_tree_block(fs_info, next);
 					btrfs_wait_tree_block_writeback(next);
 					btrfs_tree_unlock(next);
+				} else {
+					if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
+						clear_extent_buffer_dirty(next);
 				}
 
 				WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID);
@@ -2629,6 +2635,9 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
 				clean_tree_block(fs_info, next);
 				btrfs_wait_tree_block_writeback(next);
 				btrfs_tree_unlock(next);
+			} else {
+				if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
+					clear_extent_buffer_dirty(next);
 			}
 
 			WARN_ON(log->root_key.objectid !=
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html