Skip to content

x86 fault-path runs Phase-2 teardown in CPU exception context (safe on single-CPU, defer if SMP) #511

Description

@ryanbreen

Summary

Teardown P2 routes x86 page-fault/GPF exits through crate::process::exit_process_and_retire -> ProcessScheduler::handle_thread_exit (process/mod.rs:290). Its Phase 2 runs:

  • close_extracted_fds (pipe buffer.lock() / wakeups, process_task.rs:577, :381, :384)
  • scheduler::with_scheduler unblock ops (process_task.rs:585)
  • a log::debug

...synchronously inside the CPU exception (IST) context.

Adjudication: non-blocking for P2, safe today

  • x86 is single-CPU (MAX_CPUS=1), so SIGKILL teardown bypasses the hardened exit path #491's cross-CPU UAF concern does not apply here.
  • Both handlers gate on if from_userspace (CS RPL==3), meaning ring-3 was executing when the fault landed — so this CPU holds no kernel pipe/scheduler/serial spinlock at fault time. The locks taken by Phase 2 therefore cannot self-deadlock.

Follow-up required if x86 ever gains SMP

If x86 gains SMP, Phase 2 teardown must be deferred off the exception path. The machinery for this already exists: defer_fault_sigsegv_exit / drain_deferred_fault_sigsegv_exits, which runs handle_thread_exit from normal scheduling context instead of the exception handler.

Related pre-existing property (not a P2 regression)

The x86 victim page table is freed (release_process_resources -> drop(page_table.take())) while CR3 still points at it, before Cr3::write. This predates P2 and is not a regression it introduced. There is no frame-alloc in the window, so no live-CR3 corruption occurs today, but it's worth tracking alongside the above.

Reference

Phase-2 teardown PR: (see recent teardown/quiescence PRs on main, e.g. #417 and related fix/teardown-* branches).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions