Skip to content

Close PID-reuse race in orphan-Firecracker termination (pidfd + durable identity) #304

Description

@jrimmer

Problem

PR #299 (kill orphaned Firecracker processes on controller startup) validates a persisted PID with a /proc/<pid>/comm == "firecracker" check before sending SIGKILL. The code documents this as an incomplete guard:

Limitation: this is NOT complete PID-reuse protection. If a [Firecracker process's] PID is recycled and now belongs to a different Firecracker process (e.g. a freshly-spawned sandbox), the comm check still matches and the wrong VM is killed.

A controller restart can therefore SIGKILL an unrelated, healthy Firecracker VM if its PID collides with a stale registry entry — a cross-tenant destructive bug.

Proposed fix

Replace the comm check with durable process identity, validated at kill time:

  1. Persist identity with each registry entry. Record, alongside the PID:
    • process start time (/proc/<pid>/stat field 22, in clock ticks since boot)
    • executable path (realpath of /proc/<pid>/exe)
    • working directory (readlink of /proc/<pid>/cwd)
  2. Validate before kill. On the startup orphan scan, only SIGKILL a PID whose recorded start time + exe + cwd match the live /proc values. If they diverge, the PID was recycled — prune the stale registry entry without killing.
  3. Use pidfd where available. On Linux ≥ 5.3, pidfd_open(pid) + pidfd_send_signal(pidfd, SIGKILL, ...) closes the TOCTOU window between validation and kill entirely (the fd pins the original process). Fall back to start-time validation on older kernels.

Scope

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity / isolation correctness

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions