Accessing or modifying shared objects in signal handlers can lead to race conditions, opening up security holes.
According to the "Signals and Interrupts" section of the C99 Rationale:
The C89 Committee concluded that about the only thing a strictly conforming program can do in a signal handler is to assign a value to a
volatile staticvariable which can be written uninterruptedly and promptly return.
Non-Compliant Code Example
err_msg is updated to reflect the SIGINT signal that was encountered. Issues will occur if a SIGINT is generated prior to the malloc of err_msg finishing.
#include <signal.h>
char *err_msg;
void handler() {
strcpy(err_msg, "SIGINT encountered.");
}
int main() {
signal(SIGINT, handler);
err_msg = malloc(24);
strcpy(err_msg, "No errors yet.");
/* main code loop */
return 0;
}
Compliant Solution
Signal handlers should only unconditionally set and flag, and then return.
#include <signal.h>
char *err_msg;
volatile static int e_flag = 0;
void handler() {
e_flag = 1;
}
int main() {
signal(SIGINT, handler);
err_msg = malloc(24);
strcpy(err_msg, "No errors yet.");
/* main code loop */
if(e_flag)
strcpy(err_msg, "SIGINT received.");
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 06]].
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
SIG31-C |
3 (high) |
3 (likely) |
1 (high) |
P9 |
L2 |
References
[[Dowd 06]] Chapter 13, Synchronization and State
[[ISO/IEC 03]] "Signals and Interrupts"
[[Open Group 04]] longjmp![]()
[OpenBSD] signal() Man Page![]()
[Zalewski] http://lcamtuf.coredump.cx/signals.txt![]()