It is possible to safely use the same handler for multiple signals, but doing so increases the likelihood of a security vulnerability. The delivered signal is masked and is not delivered until the registered signal handler exits. However, if this same handler is registered to handle a different signal, execution of the handler may be interrupted by this new signal. If a signal handler is constructed with the expectation that it cannot be interrupted, a vulnerability might exist. To eliminate this attack vector, each signal handler should only be registered to handle one type of signal.
Non-Compliant Coding Example
The non-compliant program registers a signal handler to clean up and terminate when the process receives either a SIGINT
or a SIGTERM
. However, if a SIGINT
is generated, and then a SIGTERM
is generated after the call to free()
, but before _Exit()
is reached, a double free()
occurs. Note that this example also violates SIG30-C. Only call async-safe functions within signal handlers.
#include <signal.h> char *global_ptr; void handler() { free(global_ptr); _Exit(-1); } int main(void) { global_ptr = malloc(16); if (global_ptr == NULL) { /* handle error condition */ } signal(SIGINT, handler); signal(SIGTERM, handler); /* ... */ return 0; }
Risk Assessment
Depending on the code, this could lead to any number of attacks, many of which could give root access. For an overview of some software vulnerabilities, see Zalewski's signal article.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
SIG00-A |
3 (high) |
3 (likely) |
1 (high) |
P9 |
L2 |
References
[[ISO/IEC 03]] "Signals and Interrupts"
[[Open Group 04]] longjmp
[OpenBSD] signal()
Man Page
[Zalewski] http://lcamtuf.coredump.cx/signals.txt
[[Dowd 06 ]] Chapter 13, "Synchronization and State" (Signal Interruption and Repetition)