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 static variable which can be written uninterruptedly and promptly return.

Non-Compliant Coding 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|AA. C References#Zalewski 06]\].

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SIG31-C

3 (high)

3 (likely)

1 (high)

P9

L2

References

\[[ISO/IEC 03|AA. C References#ISO/IEC 03]\] "Signals and Interrupts"
\[[Open Group 04|AA. C References#Open Group 04]\] [longjmp|http://www.opengroup.org/onlinepubs/000095399/functions/longjmp.html]
\[OpenBSD\] [{{signal()}} Man Page|http://www.openbsd.org/cgi-bin/man.cgi?query=signal]
\[Zalewski\] [http://lcamtuf.coredump.cx/signals.txt]