• Jan Kara's avatar
    select: Fix indefinitely sleeping task in poll_schedule_timeout() · 68514dac
    Jan Kara authored
    A task can end up indefinitely sleeping in do_select() ->
    poll_schedule_timeout() when the following race happens:
    
      TASK1 (thread1)             TASK2                   TASK1 (thread2)
      do_select()
        setup poll_wqueues table
        with 'fd'
                                  write data to 'fd'
                                    pollwake()
                                      table->triggered = 1
                                                          closes 'fd' thread1 is
                                                            waiting for
        poll_schedule_timeout()
          - sees table->triggered
          table->triggered = 0
          return -EINTR
        loop back in do_select()
    
    But at this point when TASK1 loops back, the fdget() in the setup of
    poll_wqueues fails.  So now so we never find 'fd' is ready for reading
    and sleep in poll_schedule_timeout() indefinitely.
    
    Treat an fd that got closed as a fd on which some event happened.  This
    makes sure cannot block indefinitely in do_select().
    
    Another option would be to return -EBADF in this case but that has a
    potential of subtly breaking applications that excercise this behavior
    and it happens to work for them.  So returning fd as active seems like a
    safer choice.
    Suggested-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    CC: stable@vger.kernel.org
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    68514dac
select.c 34.7 KB