A signal is a mechanism for transferring control that is typically used to notify a process that an event has occurred. That process can then respond to that the event accordingly. C99 provides The C Standard provides functions for sending and handling signals within a C program.
Processes handle signals by registering a signal handler using the signal()
function, which is specified as
Code Block |
---|
void (*signal(int sig, void (*func)(int)))(int);
|
This signal handler is conceptually equivalent to
Code Block |
---|
typedef void (*sighandler_t)(int signum);
extern sighandler_t signal(
int signum,
sighandler_t handler
);
|
...
Some platforms provide the ability to mask signals while a signal handler is being processed. If a signal is masked while its own handler is processed, the handler is noninterruptible and need not be async-signal-safe. However, even when a signal is masked while its own handler is processed, the handler must still avoid invoking async-signal-safe unsafe functions because their execution may be (or have been) interrupted by another signal.
Vulnerabilities can arise if a signal handler that is not async-signal-safe is interrupted with any unmasked signal, including its own.
...
This noncompliant code example registers a single signal handler to process both SIGUSR1
and SIGUSR2
. The variable sig2
should be set to 1
if one or more SIGUSR1
signals are followed by SIGUSR2
, essentially implementing a finite state machine within the signal handler.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h>
volatile sig_atomic_t sig1 = 0;
volatile sig_atomic_t sig2 = 0;
void handler(int signum) {
if (signum == SIGUSR1) {
sig1 = 1;
}
else if (sig1) {
sig2 = 1;
}
}
int main(void) {
if (signal(SIGUSR1, handler) == SIG_ERR) {
/* Handle error */
}
if (signal(SIGUSR2, handler) == SIG_ERR) {
/* Handler error */
}
while (sig2 == 0) {
/* Do nothing or give up CPU for a while */
}
/* ... */
return 0;
}
|
Unfortunately, there is a race condition occurs in the implementation of handler()
. If handler()
is called to handle SIGUSR1
and is interrupted to handle SIGUSR2
, it is possible that sig2
will not be set.
...
The POSIX sigaction()
function assigns handlers to signals in a similar manner to the C99 C signal()
function, but it also allows signal masks to be set explicitly. Consequently, sigaction()
can be used to prevent a signal handler from interrupting itself.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <signal.h>
#include <stdio.h>
volatile sig_atomic_t sig1 = 0;
volatile sig_atomic_t sig2 = 0;
void handler(int signum) {
if (signum == SIGUSR1) {
sig1 = 1;
}
else if (sig1) {
sig2 = 1;
}
}
int main(void) {
struct sigaction act;
act.sa_handler = &handler;
act.sa_flags = 0;
if (sigemptyset(&act.sa_mask) != 0) {
/* Handle error */
}
if (sigaddset(&act.sa_mask, SIGUSR1)) {
/* Handle error */
}
if (sigaddset(&act.sa_mask, SIGUSR2)) {
/* Handle error */
}
if (sigaction(SIGUSR1, &act, NULL) != 0) {
/* Handle error */
}
if (sigaction(SIGUSR2, &act, NULL) != 0) {
/* Handle error */
}
while (sig2 == 0) {
/* Do nothing or give up CPU for a while */
}
/* ... */
return 0;
}
|
POSIX recommends sigaction()
and deprecates the use of signal()
to register signal handlers. Unfortunately, sigaction()
is not defined in C99 and in the C Standard and is consequently not as portable a solution.
Risk Assessment
Interrupting a noninterruptible signal handler can result in a variety of vulnerabilities \[ [Zalewski 2001|AA. Bibliography#Zalewski 01]\]. Wiki Markup
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
SIG00-C |
High |
Likely |
High | P9 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| BADFUNC.SIGNAL | Use of signal | ||||||
Helix QAC |
| C5019 | |||||||
LDRA tool suite |
| 44 S | Enhanced enforcement | ||||||
Parasoft C/C++test |
| CERT_C-SIG00-a | The signal handling facilities of <signal.h> shall not be used | ||||||
PC-lint Plus |
| 586 | Assistance provided: reports use of the signal function |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
...
...
...
...
Insufficient |
...
synchronization |
Bibliography
[C99 Rationale 2003] | Subclause |
...
5.2.3, "Signals and |
...
Interrupts" |
Bibliography
...
[ |
...
...
...
] | Chapter 13, |
...
"Synchronization |
...
and |
...
State" |
...
("Signal |
...
Interruption |
...
and |
...
Repetition") | |
[IEEE Std 1003.1:2013] | XSH, System Interface, longjmp |
[OpenBSD] | signal() Man Page |
[Zalewski 2001] | "Delivering Signals for Fun and Profit" |
...
\[[Open Group 2004|AA. Bibliography#Open Group 04]\] [longjmp|http://www.opengroup.org/onlinepubs/000095399/functions/longjmp.html] \[[OpenBSD|AA. Bibliography#OpenBSD]\] [{{signal()}} Man Page|http://www.openbsd.org/cgi-bin/man.cgi?query=signal] \[[Zalewski 2001|AA. Bibliography#Zalewski 01]\]11. Signals (SIG) 11. Signals (SIG)