[PATCH 63/67] xfs: fix a use after free in xfs_defer_finish_recovery

Darrick J. Wong
2024-03-26T03:19:17Z

From: Christoph Hellwig <hch@lst.de>

Source kernel commit: 4f6ac47b55e3ce6e982807928d6074ec105ab66e

dfp will be freed by ->recover_work and thus the tracepoint in case
of an error can lead to a use after free.

Store the defer ops in a local variable to avoid that.

Fixes: 7f2f7531e0d4 ("xfs: store an ops pointer in struct xfs_defer_pending")
Reported-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
Reviewed-by: Bill O'Donnell <bodonnel@redhat.com>
---
libxfs/xfs_defer.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c
index 077e99298074..5bdc8f5a258a 100644
--- a/libxfs/xfs_defer.c
+++ b/libxfs/xfs_defer.c
@@ -909,12 +909,14 @@ xfs_defer_finish_recovery(
struct xfs_defer_pending *dfp,
struct list_head *capture_list)
{
+ const struct xfs_defer_op_type *ops = dfp->dfp_ops;
int error;

- error = dfp->dfp_ops->recover_work(dfp, capture_list);
+ /* dfp is freed by recover_work and must not be accessed afterwards */
+ error = ops->recover_work(dfp, capture_list);
if (error)
trace_xlog_intent_recovery_failed(mp, error,
- dfp->dfp_ops->recover_work);
+ ops->recover_work);
return error;
}