A signal handler should not reassert its desire to handle its own signal. This is often done on nonpersistent platforms—that is, platforms that, upon receiving a signal, reset the handler for the signal to SIG_DFL before calling the bound signal handler. Calling signal()
under these conditions presents a race condition. (see See SIG01-C. Understand implementation-specific details regarding signal handler persistence.).
A signal handler may call signal()
only if it does not need to be asynchronous-safe (that is, if all relevant signals are masked so that the handler cannot be interrupted).
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h>
#include <stddef.h>
void handler(int signum) {
/* Handle signal */
}
void func(void) {
struct sigaction act;
act.sa_handler = handler;
act.sa_flags = 0;
if (sigemptyset(&act.sa_mask) != 0) {
/* Handle error */
}
if (sigaction(SIGUSR1, &act, NULL) != 0) {
/* Handle error */
}
} |
...
Compliant Solution (Windows)
There are two classes of signals in the Visual C++ implementation:
SIGSEGV
,SIGILL
, andSIGFPE
have per-thread handlers, so each thread may register its own handler for these signals.SIGABRT
,SIGBREAK
,SIGTERM
, andSIGINT
have global handlers and access to these handlers is synchronized via a global lock.
There is no safe way to implement persistent signal-handler behavior on Windows platforms, and it should not be attempted. If a design depends on this behavior, and the design cannot be altered, it may be necessary to claim a deviation from this rule after completing an appropriate risk analysis.
The reason for this is that Windows is a nonpersistent platform as discussed above. Just before calling the current handler function, Windows resets the handler for the next occurrence of the same signal to SIG_DFL
. If the handler calls signal()
to reinstall itself, there is still a race window. A signal might occur between the start of the handler and the call to signal()
, which would invoke the default behavior instead of the desired handlerFor the signals with global handlers, the handler is reset to SIG_DFL
and the handler is called under a lock, so there is no race if signal()
is called again from the handler to reassert itself as the handler. For the signals with per-thread handlers, the state is local to the thread and resultantly there is no opportunity for a race.
Exceptions
SIG34-C-EX1: For implementations with persistent signal handlers, it is safe for a handler to modify the behavior of its own signal. Behavior modifications include ignoring the signal, resetting to the default behavior, and having the signal handled by a different handler. A handler reasserting its binding is also safe but unnecessary.
...
Two signals in quick succession can trigger a race condition on nonpersistent platforms, causing the signal's default behavior despite a handler's attempt to override it.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
SIG34-C | Low | Unlikely | Low | P3 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| signal-handler-signal-call | Partially checked | ||||||
Axivion Bauhaus Suite |
| CertC-SIG34 | |||||||
CodeSonar |
| BADFUNC.SIGNAL | Use of signal | ||||||
Compass/ROSE |
Can detect violations of this rule. However, false positives may occur on systems with persistent handlers | |||||||||
Cppcheck Premium |
| premium-cert-sig34-c | Fully implemented | ||||||
Helix QAC |
| C5021 C++5022 | |||||||
Klocwork |
| MISRA.STDLIB.SIGNAL | |||||||
LDRA tool suite |
| 97 D | Fully implemented | ||||||
Parasoft C/C++test |
| CERT_C-SIG34-a | Properly define signal handlers | |||||||
PC-lint Plus |
| 2762, 2763 | Fully supported | ||||||
| CERT C: Rule SIG34-C | Checks for signal call from within signal handler (rule partially covered) | |||||||
RuleChecker |
| signal-handler-signal-call | Partially checked |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
---|---|---|
CERT C Secure Coding Standard | SIG01-C. Understand implementation-specific details regarding signal handler persistence | Prior to 2018-01-12: CERT: Unspecified Relationship |
ISO/IEC TS 17961:2013 | Calling signal from interruptible signal handlers [sigcall] |
...
Prior to 2018-01-12: CERT: Unspecified Relationship |
...