Skip to content

pidfd close can tear down a newer pidfd that reused the fd number #403

Description

@xalestar

Closing a pidfd tears down its entry in pidfd_table by guest fd number alone, after the fd slot has already been released, so a concurrent pidfd_open that reuses the number can lose its entry to the old fd's cleanup.

sys_close calls fd_snapshot_and_close, which marks the slot closed under fd_lock and drops the lock. fd_cleanup_entry then runs pidfd_cleanup(guest_fd) with no lock held. In that window another guest thread can call pidfd_open, receive the same fd number, and take a lower free index in pidfd_table. pidfd_cleanup then finds the new entry first and deactivates it, and the old entry stays active under that fd number:

  1. Thread A closes fd 5, a pidfd on pid 42 in slot 3. The fd slot is released.
  2. Thread B opens a pidfd on pid 99, receives fd 5, and is placed in slot 0.
  3. Thread A's pidfd_cleanup(5) finds slot 0 first and tears down B's entry.
  4. pidfd_send_signal(5, ...) on thread B looks up fd 5, finds slot 3, and signals pid 42.

#399 gave each pidfd a generation number so a failing monitor completes only its own entry, but the close path still matches by fd number. The cleanup callback receives only the fd number, so closing this means carrying the generation into cleanup, either by storing it in fd_entry_t or by passing the snapshot through, and having pidfd_cleanup match on it.

Raised in review of #399.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions