ext4: fix race when reusing xattr blocks
When ext4_xattr_block_set() decides to remove xattr block the following race can happen: CPU1 CPU2 ext4_xattr_block_set() ext4_xattr_release_block() new_bh = ext4_xattr_block_cache_find() lock_buffer(bh); ref = le32_to_cpu(BHDR(bh)->h_refcount); if (ref == 1) { ... mb_cache_entry_delete(); unlock_buffer(bh); ext4_free_blocks(); ... ext4_forget(..., bh, ...); jbd2_journal_revoke(..., bh); ext4_journal_get_write_access(..., new_bh, ...) do_get_write_access() jbd2_journal_cancel_revoke(..., new_bh); Later the code in ext4_xattr_block_set() finds out the block got freed and cancels reusal of the block but the revoke stays canceled and so in case of block reuse and journal replay the filesystem can get corrupted. If the race works out slightly differently, we can also hit assertions in the jbd2 code. Fix the problem by making sure that once matching mbcache entry is found, code dropping the last xattr block reference (or trying to modify xattr block in place) waits until the mbcache entry reference is dropped. This way code trying to reuse xattr block is protected from someone trying to drop the last reference to xattr block. Reported-and-tested-by:Ritesh Harjani <ritesh.list@gmail.com> CC: stable@vger.kernel.org Fixes: 82939d79 ("ext4: convert to mbcache2") Signed-off-by:
Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20220712105436.32204-5-jack@suse.cz Signed-off-by:
Theodore Ts'o <tytso@mit.edu>
parent
fd48e9ac
-
mentioned in commit 1be97463
-
mentioned in commit c6fac5cf
-
mentioned in commit 96fa141f
-
mentioned in commit 127b80ce
-
mentioned in commit cc1538c6
-
mentioned in commit 5bc0b2fd
-
mentioned in commit 1a56cd97
-
mentioned in commit 1be16a0c
-
mentioned in commit 98953044
-
mentioned in commit efaa0ca6
-
mentioned in commit af8ecc8d
-
mentioned in commit af530652
Please register or sign in to comment