Skip to content

Commit c7f87f3

Browse files
Dave ChinnerDarrick J. Wong
authored andcommitted
xfs: fix use-after-free on CIL context on shutdown
xlog_wait() on the CIL context can reference a freed context if the waiter doesn't get scheduled before the CIL context is freed. This can happen when a task is on the hard throttle and the CIL push aborts due to a shutdown. This was detected by generic/019: thread 1 thread 2 __xfs_trans_commit xfs_log_commit_cil <CIL size over hard throttle limit> xlog_wait schedule xlog_cil_push_work wake_up_all <shutdown aborts commit> xlog_cil_committed kmem_free remove_wait_queue spin_lock_irqsave --> UAF Fix it by moving the wait queue to the CIL rather than keeping it in in the CIL context that gets freed on push completion. Because the wait queue is now independent of the CIL context and we might have multiple contexts in flight at once, only wake the waiters on the push throttle when the context we are pushing is over the hard throttle size threshold. Fixes: 0e7ab7e ("xfs: Throttle commits on delayed background CIL push") Reported-by: Yu Kuai <[email protected]> Signed-off-by: Dave Chinner <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent b3a9e3b commit c7f87f3

File tree

2 files changed

+6
-6
lines changed

2 files changed

+6
-6
lines changed

fs/xfs/xfs_log_cil.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,8 @@ xlog_cil_push_work(
671671
/*
672672
* Wake up any background push waiters now this context is being pushed.
673673
*/
674-
wake_up_all(&ctx->push_wait);
674+
if (ctx->space_used >= XLOG_CIL_BLOCKING_SPACE_LIMIT(log))
675+
wake_up_all(&cil->xc_push_wait);
675676

676677
/*
677678
* Check if we've anything to push. If there is nothing, then we don't
@@ -743,13 +744,12 @@ xlog_cil_push_work(
743744

744745
/*
745746
* initialise the new context and attach it to the CIL. Then attach
746-
* the current context to the CIL committing lsit so it can be found
747+
* the current context to the CIL committing list so it can be found
747748
* during log forces to extract the commit lsn of the sequence that
748749
* needs to be forced.
749750
*/
750751
INIT_LIST_HEAD(&new_ctx->committing);
751752
INIT_LIST_HEAD(&new_ctx->busy_extents);
752-
init_waitqueue_head(&new_ctx->push_wait);
753753
new_ctx->sequence = ctx->sequence + 1;
754754
new_ctx->cil = cil;
755755
cil->xc_ctx = new_ctx;
@@ -937,7 +937,7 @@ xlog_cil_push_background(
937937
if (cil->xc_ctx->space_used >= XLOG_CIL_BLOCKING_SPACE_LIMIT(log)) {
938938
trace_xfs_log_cil_wait(log, cil->xc_ctx->ticket);
939939
ASSERT(cil->xc_ctx->space_used < log->l_logsize);
940-
xlog_wait(&cil->xc_ctx->push_wait, &cil->xc_push_lock);
940+
xlog_wait(&cil->xc_push_wait, &cil->xc_push_lock);
941941
return;
942942
}
943943

@@ -1216,12 +1216,12 @@ xlog_cil_init(
12161216
INIT_LIST_HEAD(&cil->xc_committing);
12171217
spin_lock_init(&cil->xc_cil_lock);
12181218
spin_lock_init(&cil->xc_push_lock);
1219+
init_waitqueue_head(&cil->xc_push_wait);
12191220
init_rwsem(&cil->xc_ctx_lock);
12201221
init_waitqueue_head(&cil->xc_commit_wait);
12211222

12221223
INIT_LIST_HEAD(&ctx->committing);
12231224
INIT_LIST_HEAD(&ctx->busy_extents);
1224-
init_waitqueue_head(&ctx->push_wait);
12251225
ctx->sequence = 1;
12261226
ctx->cil = cil;
12271227
cil->xc_ctx = ctx;

fs/xfs/xfs_log_priv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ struct xfs_cil_ctx {
240240
struct xfs_log_vec *lv_chain; /* logvecs being pushed */
241241
struct list_head iclog_entry;
242242
struct list_head committing; /* ctx committing list */
243-
wait_queue_head_t push_wait; /* background push throttle */
244243
struct work_struct discard_endio_work;
245244
};
246245

@@ -274,6 +273,7 @@ struct xfs_cil {
274273
wait_queue_head_t xc_commit_wait;
275274
xfs_lsn_t xc_current_sequence;
276275
struct work_struct xc_push_work;
276+
wait_queue_head_t xc_push_wait; /* background push throttle */
277277
} ____cacheline_aligned_in_smp;
278278

279279
/*

0 commit comments

Comments
 (0)