Skip to content

Signal Handler Violates Async-Signal-Safety Requirements [lazy pages] #5051

@Nathanbyarugaba

Description

@Nathanbyarugaba

Problem

Location: user_signal_handler
The signal handler user_signal_handler violates POSIX async-signal-safety requirements by performing operations that are not async-signal-safe.
This creates multiple attack vectors for denial-of-service.

Async-Signal-Safety Violations:

  1. Thread-Local Storage Access (line 107): LAZY_PAGES_CONTEXT.with() accesses thread-local storage, which may involve locks or allocation.

  2. RefCell::borrow_mut() (line 108): This operation can panic if the RefCell is already borrowed. With the SA_NODEFER flag set
    (sys/unix.rs:231), nested signals are possible, causing:

    • First signal: borrows RefCell
    • Nested signal arrives: attempts to borrow_mut() again → panic
  3. Logging with Allocation (line 106): log::debug!() with format strings typically allocates memory for string formatting. If malloc's internal
    locks are held when the signal arrives, this causes deadlock:

    • Main thread: holds malloc lock
    • Signal interrupts during malloc
    • Signal handler: calls log::debug!() → attempts malloc → deadlock

Steps

Attack Vector:

1. Attacker triggers page fault (e.g., accessing lazy page)
2. Signal handler begins executing
3. Before handler completes, trigger second page fault (possible with SA_NODEFER)
4. Second handler attempts borrow_mut() on already-borrowed RefCell
5. Panic occurs in signal handler → process crash

Possible Solution

POSIX Requirements:
From POSIX.1-2008: "A signal-catching function shall call only async-signal-safe functions." The only guaranteed async-signal-safe operations are
specific syscalls and atomic operations. Memory allocation, locking, and TLS access are explicitly NOT async-signal-safe.

Current Code Uses SA_NODEFER:
In sys/unix.rs:231, the signal handler is registered with SA_NODEFER, which explicitly allows signal reentrancy:

signal::SigAction::new(
    handler,
    signal::SaFlags::SA_SIGINFO | signal::SaFlags::SA_ONSTACK | signal::SaFlags::SA_NODEFER,
    signal::SigSet::empty(),
)

This makes nested signals not just theoretical but explicitly supported, increasing exploitability.

Notes

No response

Relevant Log Output

Click to expand/collapse

<Paste your log here>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions