Do not call non-reentrant functions within signal handlers. This could result in several issues, including heap damage and semantic vulnerabilities.

According to the "Signals and Interrupts" section of the C99 Rationale:

When a signal occurs, the normal flow of control of a program is interrupted. If a signal occurs that is being trapped by a signal handler, that handler is invoked. When it is finished, execution continues at the point at which the signal occurred. This arrangement could cause problems if the signal handler invokes a library function that was being executed at the time of the signal. Since library functions are not guaranteed to be reentrant, they should not be called from a signal handler that returns.

Implementation Details

The OpenBSD signal() man page identifies functions that are either reentrant or not interruptible by signals and are asynchronous-signal safe. Applications may therefore invoke them, without restriction, from signal-catching functions.

Non-Compliant Code Example

This non-compliant code example invokes the free function from within the signal handler. If an interrupt signal is received during or after the free call in main, the heap will be corrupted.

#include <signal.h>  
 
char *foo;  
 
void int_handler() { 
  free(foo); 
  _Exit(0); 
} 
  
int main(void) {  
  foo = malloc(15); 
  signal(SIGINT, int_handler);  
 
  strcpy(foo, "Hello World."); 
  puts(foo); 
 
  free(foo); 
  return 0; 
} 

Compliant Solution

Signal handlers should be as minimal as possible, only unconditionally setting a flag where appropriate, and returning. You may also call the _exit function to immediately terminate program execution.

#include <signal.h>  
 
char *foo;  
 
void int_handler() { 
  _Exit(0); 
} 
  
int main(void) {  
  foo = malloc(15); 
  signal(SIGINT, int_handler);  
 
  strcpy(foo, "Hello World."); 
  puts(foo); 
 
  free(foo); 
  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. VU #834865 is also an example of this.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SIG00-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 01\] [http://lcamtuf.coredump.cx/signals.txt]