Skip to content

Commit 01d7a35

Browse files
committed
aio: prevent potential eventfd recursion on poll
If we have nested or circular eventfd wakeups, then we can deadlock if we run them inline from our poll waitqueue wakeup handler. It's also possible to have very long chains of notifications, to the extent where we could risk blowing the stack. Check the eventfd recursion count before calling eventfd_signal(). If it's non-zero, then punt the signaling to async context. This is always safe, as it takes us out-of-line in terms of stack and locking context. Cc: [email protected] # 4.19+ Reviewed-by: Jeff Moyer <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 3e577dc commit 01d7a35

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

fs/aio.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,14 @@ static int aio_fsync(struct fsync_iocb *req, const struct iocb *iocb,
16101610
return 0;
16111611
}
16121612

1613+
static void aio_poll_put_work(struct work_struct *work)
1614+
{
1615+
struct poll_iocb *req = container_of(work, struct poll_iocb, work);
1616+
struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll);
1617+
1618+
iocb_put(iocb);
1619+
}
1620+
16131621
static void aio_poll_complete_work(struct work_struct *work)
16141622
{
16151623
struct poll_iocb *req = container_of(work, struct poll_iocb, work);
@@ -1674,6 +1682,8 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
16741682
list_del_init(&req->wait.entry);
16751683

16761684
if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) {
1685+
struct kioctx *ctx = iocb->ki_ctx;
1686+
16771687
/*
16781688
* Try to complete the iocb inline if we can. Use
16791689
* irqsave/irqrestore because not all filesystems (e.g. fuse)
@@ -1683,8 +1693,14 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
16831693
list_del(&iocb->ki_list);
16841694
iocb->ki_res.res = mangle_poll(mask);
16851695
req->done = true;
1686-
spin_unlock_irqrestore(&iocb->ki_ctx->ctx_lock, flags);
1687-
iocb_put(iocb);
1696+
if (iocb->ki_eventfd && eventfd_signal_count()) {
1697+
iocb = NULL;
1698+
INIT_WORK(&req->work, aio_poll_put_work);
1699+
schedule_work(&req->work);
1700+
}
1701+
spin_unlock_irqrestore(&ctx->ctx_lock, flags);
1702+
if (iocb)
1703+
iocb_put(iocb);
16881704
} else {
16891705
schedule_work(&req->work);
16901706
}

0 commit comments

Comments
 (0)