diff options
author | Brian Foster <bfoster@redhat.com> | 2019-04-12 10:39:19 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-04-14 21:15:56 -0400 |
commit | 4d09807f20462d6edf04f6e98d3d47bcdf7a5e2f (patch) | |
tree | a9cc42a695f26db2fee2fa03fe1749bacd5cefb8 | |
parent | dc4060a5dc2557e6b5aa813bf5b73677299d62d2 (diff) |
xfs: fix use after free in buf log item unlock assert
The xfs_buf_log_item ->iop_unlock() callback asserts that the buffer
is unlocked when either non-stale or aborted. This assert occurs
after the bli refcount has been dropped and the log item potentially
freed. The aborted check is thus a potential use after free. This
problem has been reproduced with KASAN enabled via generic/475.
Fix up xfs_buf_item_unlock() to query aborted state before the bli
reference is dropped to prevent a potential use after free.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 010db5f8fb00..65b32acfa0f6 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -605,6 +605,8 @@ xfs_buf_item_unlock( | |||
605 | #if defined(DEBUG) || defined(XFS_WARN) | 605 | #if defined(DEBUG) || defined(XFS_WARN) |
606 | bool ordered = bip->bli_flags & XFS_BLI_ORDERED; | 606 | bool ordered = bip->bli_flags & XFS_BLI_ORDERED; |
607 | bool dirty = bip->bli_flags & XFS_BLI_DIRTY; | 607 | bool dirty = bip->bli_flags & XFS_BLI_DIRTY; |
608 | bool aborted = test_bit(XFS_LI_ABORTED, | ||
609 | &lip->li_flags); | ||
608 | #endif | 610 | #endif |
609 | 611 | ||
610 | trace_xfs_buf_item_unlock(bip); | 612 | trace_xfs_buf_item_unlock(bip); |
@@ -633,7 +635,7 @@ xfs_buf_item_unlock( | |||
633 | released = xfs_buf_item_put(bip); | 635 | released = xfs_buf_item_put(bip); |
634 | if (hold || (stale && !released)) | 636 | if (hold || (stale && !released)) |
635 | return; | 637 | return; |
636 | ASSERT(!stale || test_bit(XFS_LI_ABORTED, &lip->li_flags)); | 638 | ASSERT(!stale || aborted); |
637 | xfs_buf_relse(bp); | 639 | xfs_buf_relse(bp); |
638 | } | 640 | } |
639 | 641 | ||