summaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs/xfs_defer.h
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-05-15 17:16:37 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2020-06-01 21:16:47 -0700
commitd58d95cbbc5ae1010731b8cf0f276e98ed17f135 (patch)
tree45975dc9810e3f3ee9553a13563d5b24b4afda19 /fs/xfs/libxfs/xfs_defer.h
parente891f9ca97b6af70d8385d75e6cea62307ec02cc (diff)
xfs: fix an incore inode UAF in xfs_bui_recoverfix-log-recovery_2020-06-01
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_defer.h')
-rw-r--r--fs/xfs/libxfs/xfs_defer.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index a0ad379e38f8..532439dc5ec9 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -77,6 +77,11 @@ struct xfs_defer_capture {
struct list_head dfc_dfops;
unsigned int dfc_tpflags;
unsigned int dfc_blkres;
+
+ /* Inodes to hold when we want to finish the deferred work items. */
+ unsigned int dfc_ilockflags;
+#define XFS_DEFER_CAPTURE_INODES 2
+ struct xfs_inode *dfc_inodes[XFS_DEFER_CAPTURE_INODES];
};
/*
@@ -87,5 +92,12 @@ int xfs_defer_capture(struct xfs_trans *tp, struct xfs_defer_capture **dfcp);
void xfs_defer_continue(struct xfs_defer_capture *dfc, struct xfs_trans *tp);
void xfs_defer_capture_free(struct xfs_mount *mp,
struct xfs_defer_capture *dfc);
+int xfs_defer_capture_inode(struct xfs_defer_capture *dfc,
+ struct xfs_inode *ip);
+
+/* These functions must be provided by the xfs implementation. */
+void xfs_defer_continue_inodes(struct xfs_defer_capture *dfc,
+ struct xfs_trans *tp);
+void xfs_defer_capture_irele(struct xfs_defer_capture *dfc);
#endif /* __XFS_DEFER_H__ */