• Suren Baghdasaryan's avatar
    pidfd: fix a poll race when setting exit_state · b191d649
    Suren Baghdasaryan authored
    There is a race between reading task->exit_state in pidfd_poll and
    writing it after do_notify_parent calls do_notify_pidfd. Expected
    sequence of events is:
    
    CPU 0                            CPU 1
    ------------------------------------------------
    exit_notify
      do_notify_parent
        do_notify_pidfd
      tsk->exit_state = EXIT_DEAD
                                      pidfd_poll
                                         if (tsk->exit_state)
    
    However nothing prevents the following sequence:
    
    CPU 0                            CPU 1
    ------------------------------------------------
    exit_notify
      do_notify_parent
        do_notify_pidfd
                                       pidfd_poll
                                          if (tsk->exit_state)
      tsk->exit_state = EXIT_DEAD
    
    This causes a polling task to wait forever, since poll blocks because
    exit_state is 0 and the waiting task is not notified again. A stress
    test continuously doing pidfd poll and process exits uncovered this bug.
    
    To fix it, we make sure that the task's exit_state is always set before
    calling do_notify_pidfd.
    
    Fixes: b53b0b9d ("pidfd: add polling support")
    Cc: kernel-team@android.com
    Cc: Oleg Nesterov <oleg@redhat.com>
    Signed-off-by: default avatarSuren Baghdasaryan <surenb@google.com>
    Signed-off-by: default avatarJoel Fernandes (Google) <joel@joelfernandes.org>
    Link: https://lore.kernel.org/r/20190717172100.261204-1-joel@joelfernandes.org
    [christian@brauner.io: adapt commit message and drop unneeded changes from wait_task_zombie]
    Signed-off-by: default avatarChristian Brauner <christian@brauner.io>
    b191d649
exit.c 44.5 KB