diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2020-06-25 18:18:55 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2020-09-14 19:10:43 -0700 |
commit | 5cd779f671fc7c7e802a7e26bbf513bc02da80a1 (patch) | |
tree | 53cf893f49f9a041ea13545937c32b8380ce37ab /fs/xfs/libxfs/xfs_log_recover.h | |
parent | 4e5df2c4b07f7e8ed6dd7ed188fb9d26d58ab611 (diff) |
xfs: fix an incore inode UAF in xfs_bui_recoverfix-log-recovery_2020-09-14
In xfs_bui_item_recover, there exists a use-after-free bug with regards
to the inode that is involved in the bmap replay operation. If the
mapping operation does not complete, we call xfs_bmap_unmap_extent to
create a deferred op to finish the unmapping work, and we retain a
pointer to the incore inode.
Unfortunately, the very next thing we do is commit the transaction and
drop the inode. If reclaim tears down the inode before we try to finish
the defer ops, we dereference garbage and blow up. Therefore, create a
way to join inodes to the defer ops freezer so that we can maintain the
xfs_inode reference until we're done with the inode.
Note: This imposes the requirement that there be enough memory to keep
every incore inode in memory throughout recovery.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/libxfs/xfs_log_recover.h')
-rw-r--r-- | fs/xfs/libxfs/xfs_log_recover.h | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_log_recover.h b/fs/xfs/libxfs/xfs_log_recover.h index c3563c5c033c..e8aba7c6e851 100644 --- a/fs/xfs/libxfs/xfs_log_recover.h +++ b/fs/xfs/libxfs/xfs_log_recover.h @@ -127,7 +127,17 @@ void xlog_recover_iodone(struct xfs_buf *bp); void xlog_recover_release_intent(struct xlog *log, unsigned short intent_type, uint64_t intent_id); -int xlog_recover_trans_commit(struct xfs_trans *tp, - struct xfs_defer_capture **dfcp); +int xlog_recover_trans_commit_inodes(struct xfs_trans *tp, + struct xfs_defer_capture **dfcp, struct xfs_inode *ip1, + struct xfs_inode *ip2); + +static inline int +xlog_recover_trans_commit( + struct xfs_trans *tp, + struct xfs_defer_capture **dfcp) +{ + return xlog_recover_trans_commit_inodes(tp, dfcp, NULL, NULL); +} + #endif /* __XFS_LOG_RECOVER_H__ */ |