CWE-432 covers a signal handler that shares state with other handlers but does not mask or prevent those handlers from running while it is still executing.
How it happens
A handler can be interrupted by another signal. If both handlers touch the same global variables, an attacker who sends a second signal at the right moment can corrupt the state before the first handler finishes.
/* Vulnerable: two handlers share global state, no mask */
volatile int *buf;
void on_term(int s) { free((void*)buf); buf = NULL; }
void on_hup(int s) { free((void*)buf); buf = NULL; }
signal(SIGTERM, on_term);
signal(SIGHUP, on_hup);
If SIGHUP arrives during the free in the first handler, memory management can go wrong. MITRE does not list an observed CVE for this exact entry, but a related chain appears under CWE-415 where a signal handler race led to a double free.
What an attacker gains
Per the record: integrity, through modified application data.
How to find it
No detection methods are listed. Review signal handlers for calls to non async-signal-safe functions and for shared state.
How to fix it
- Use
sigactionwithsa_maskto block other signals while a handler runs. - Keep handlers tiny: set a flag and return.
- Do the real work in the main loop.
volatile sig_atomic_t got_term = 0;
void on_term(int s) { got_term = 1; }
struct sigaction sa = {0};
sa.sa_handler = on_term;
sigfillset(&sa.sa_mask); /* block all signals during handler */
sigaction(SIGTERM, &sa, NULL);
What async-signal-safe means
POSIX defines a short list of functions that are safe to call from a signal handler. Memory allocation, most of the standard I/O library and anything that takes a lock are not on it. A handler that calls them can deadlock or corrupt state when the signal lands in the middle of the same operation in the main program. Keeping handlers to a flag write removes that whole class of problem.
Quick check
Why set a flag instead of doing work in the handler?
Handlers can interrupt code at any point, so little is safe to call from them. A flag is safe, and the main loop does the rest.