signal-handler · git:20261016.fb3b156 · 2026-10-16 · sha256 a689a8a54253e2fc
signal-handler git:20261016.fb3b156A
Immutable. This exact content never changes and is served at /api/v1/blob/a689a8a54253e2fc.
--- name: signal-handler description: Classify signal handler evidence — a signal(2) handler that calls a non-async-signal-safe libc function. Maps to CWE-479. license: MIT compatibility: opencode,claude code,DSH metadata: cwe: CWE-479 severity: HIGH domain: security --- ## Signal Handler Analysis (CWE-479) ### Evidence Pattern A signal-handler candidate has: - **signal_handler_unsafe**: the non-async-signal-safe call (e.g. `malloc`, `printf`, `pthread_mutex_lock`) with category `signal_handler_unsafe` - The event's `function` is the handler registered via `signal(SIGxxx, handler)` - **call_path**: The registering function is reachable from an entry point ### Detection Logic 1. Find `signal(SIGxxx, handler)` registrations where `handler` is a named function (not `SIG_DFL`/`SIG_IGN`) 2. Find the handler's function definition 3. Emit `SIGNAL_HANDLER` for each DIRECT call to a known non-async-signal-safe libc function in its body ### Classification Rules | Condition | Classification | |-----------|---------------| | A registered handler calls `malloc`/`free`/`printf`/`pthread_mutex_lock`/`syslog`/... | **confirmed** | | The handler calls only async-signal-safe functions (`write`, `close`, `fork`, `_exit`, ...) | **false-positive** (the detector never emits it) | The unsafe list is the POSIX async-signal-safe list inverted: a direct call to a function absent from that list is a certain defect, so the pipeline auto-confirms it. `read`/`write`/`open`/`close`/`socket`/`send`/`recv`/`connect`/`fcntl`/`fork`/ `exec*`/`_exit`/`abort` are async-signal-safe and are never reported. ### Common False Positives - The detector only reports DIRECT calls in the handler body; it never flags a helper function the handler calls (transitive cases are out of scope), and it does not flag the async-signal-safe functions listed above. ### Fix Suggestions - Do only async-signal-safe work in the handler: set a `volatile sig_atomic_t` flag and return; let the main loop do the heavy lifting - If logging is required, use `write(fd, ...)` to a pre-opened fd, not `printf`/`syslog` - Never allocate or take a lock in a signal handler ### Severity Matrix `status` and `severity` are independent: `status` = evidence verdict (confirmed/dismissed), `severity` = impact (low/medium/high/critical). `metadata.severity` is the type default, not a ceiling. The verdict is binary (confirmed/dismissed); dismissed → `low`. | Shape | Severity | |-------|----------| | Direct call to a non-async-signal-safe function in a registered handler | HIGH |