Safeguard
Application Security•

CWE-831 Signal Handler Function Associated with Multiple Signals

One handler for several signals can be interrupted by a different signal mid run. CWE-831 explains the race and the simple way to avoid it.

Safeguard Security Team
2 min read

CWE-831 is a function used as the handler for more than one signal. MITRE says this is sometimes intentional and safe. It becomes a problem when the function touches state outside its own locals.

It applies to any program that registers signal handlers, most often C code on Unix style systems.

How it happens

In many operating systems, while a handler runs for one signal, that same signal will not invoke the handler again until it finishes. A different signal sharing the same handler has no such protection. An attacker can send signal A, and while the handler runs, send signal B. The handler is interrupted mid way, and if it uses global variables, non-reentrant functions or has side effects, shared state may be corrupted.

// Vulnerable: one handler, two signals, shared global state
static char *buf;
void handler(int sig) {
    free(buf);
    buf = NULL;
    log_exit(sig);
}
sigaction(SIGTERM, &sa, NULL);   // same handler
sigaction(SIGINT,  &sa, NULL);   // for both

A second signal during the first run can lead to a double free.

What an attacker gains

MITRE says the most common result is corrupted product state, possibly a crash or exit. Depending on the state touched, the record also lists code execution, reading application data, gaining privileges and bypassing protections.

How to find it

The record lists no detection methods. Search for every registration call and see whether one function appears more than once. For each, check whether it uses anything shared.

How to fix it

The record gives no formal mitigations. Practical options:

  1. Use a separate, small handler per signal.
  2. Make handlers only set a volatile sig_atomic_t flag, then act on it in the main flow.
  3. When sharing is needed, mask the other signals while the handler runs by filling sa_mask.
sigfillset(&sa.sa_mask);   // block others during the handler

Quick check

Why is one signal safe from itself but not from another?

The system usually blocks the same signal while its handler runs. Other signals are not blocked unless you ask.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.