lkml.org 
[lkml]   [2020]   [Feb]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 122/195] aio: prevent potential eventfd recursion on poll
    Date
    From: Jens Axboe <axboe@kernel.dk>

    commit 01d7a356872eec22ef34a33a5f9cfa917d145468 upstream.

    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: stable@vger.kernel.org # 4.19+
    Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/aio.c | 20 ++++++++++++++++++--
    1 file changed, 18 insertions(+), 2 deletions(-)

    --- a/fs/aio.c
    +++ b/fs/aio.c
    @@ -1600,6 +1600,14 @@ static int aio_fsync(struct fsync_iocb *
    return 0;
    }

    +static void aio_poll_put_work(struct work_struct *work)
    +{
    + struct poll_iocb *req = container_of(work, struct poll_iocb, work);
    + struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll);
    +
    + iocb_put(iocb);
    +}
    +
    static void aio_poll_complete_work(struct work_struct *work)
    {
    struct poll_iocb *req = container_of(work, struct poll_iocb, work);
    @@ -1664,6 +1672,8 @@ static int aio_poll_wake(struct wait_que
    list_del_init(&req->wait.entry);

    if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) {
    + struct kioctx *ctx = iocb->ki_ctx;
    +
    /*
    * Try to complete the iocb inline if we can. Use
    * irqsave/irqrestore because not all filesystems (e.g. fuse)
    @@ -1673,8 +1683,14 @@ static int aio_poll_wake(struct wait_que
    list_del(&iocb->ki_list);
    iocb->ki_res.res = mangle_poll(mask);
    req->done = true;
    - spin_unlock_irqrestore(&iocb->ki_ctx->ctx_lock, flags);
    - iocb_put(iocb);
    + if (iocb->ki_eventfd && eventfd_signal_count()) {
    + iocb = NULL;
    + INIT_WORK(&req->work, aio_poll_put_work);
    + schedule_work(&req->work);
    + }
    + spin_unlock_irqrestore(&ctx->ctx_lock, flags);
    + if (iocb)
    + iocb_put(iocb);
    } else {
    schedule_work(&req->work);
    }

    \
     
     \ /
      Last update: 2020-02-10 14:33    [W:4.143 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site