• Eric Biggers's avatar
    aio: fix use-after-free due to missing POLLFREE handling · 50252e4b
    Eric Biggers authored
    signalfd_poll() and binder_poll() are special in that they use a
    waitqueue whose lifetime is the current task, rather than the struct
    file as is normally the case.  This is okay for blocking polls, since a
    blocking poll occurs within one task; however, non-blocking polls
    require another solution.  This solution is for the queue to be cleared
    before it is freed, by sending a POLLFREE notification to all waiters.
    
    Unfortunately, only eventpoll handles POLLFREE.  A second type of
    non-blocking poll, aio poll, was added in kernel v4.18, and it doesn't
    handle POLLFREE.  This allows a use-after-free to occur if a signalfd or
    binder fd is polled with aio poll, and the waitqueue gets freed.
    
    Fix this by making aio poll handle POLLFREE.
    
    A patch by Ramji Jiyani <ramjiyani@google.com>
    (https://lore.kernel.org/r/20211027011834.2497484-1-ramjiyani@google.com)
    tried to do this by making aio_poll_wake() always complete the request
    inline if POLLFREE is seen.  However, that solution had two bugs.
    First, it introduced a deadlock, as it unconditionally locked the aio
    context while holding the waitqueue lock, which inverts the normal
    locking order.  Second, it didn't consider that POLLFREE notifications
    are missed while the request has been temporarily de-queued.
    
    The second problem was solved by my previous patch.  This patch then
    properly fixes the use-after-free by handling POLLFREE in a
    deadlock-free way.  It does this by taking advantage of the fact that
    freeing of the waitqueue is RCU-delayed, similar to what eventpoll does.
    
    Fixes: 2c14fa83 ("aio: implement IOCB_CMD_POLL")
    Cc: <stable@vger.kernel.org> # v4.18+
    Link: https://lore.kernel.org/r/20211209010455.42744-6-ebiggers@kernel.orgSigned-off-by: default avatarEric Biggers <ebiggers@google.com>
    50252e4b
aio.c 60.6 KB