Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Signal handlers can be interrupted by their own signals. If a signal is not reset before its handler is called, this means the handler can essentially 'interrupt itself'interrupt its own execution. A handler that always successfully executes its code despite interrupting itself is said to be re-entrant.

...

Vulnerabilities can arise if a non-re-entrant signal handler is interrupted with its own signal, especially if it manipulates globally-accessible data.

Non-Compliant

...

Code Example

This non-compliant program code example registers a single signal handler to process both SIGUSR1 and SIGUSR2. The variable sig2 should be set to one if one or more SIGUSR1 signals are followed by SIGUSR2. This code essentially implements a finite state machine within the signal handler.

Code Block
bgColor#FFcccc
#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) {
  signal(SIGUSR1, handler);
  signal(SIGUSR2, handler);

  while (sig2 == 0) {
    /* do nothing or give up CPU for a while */
  }

  /* ... */

  return 0;
}

The problem with this code is that Unfortunately, there is a race condition 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.

This non-compliant code example also violates SIG31-C. Do not access or modify shared objects in signal handlers.

Non-Compliant

...

Code Example (External finite state machine)

This non-compliant code example moves the finite state machine out of the signal handler, making the handler re-entrant.

...

There is still a race condition in this code where a SIGUSR2 sent immediately after a SIGUSR1 gets is ignored. This is because the SIGUSR2 gets is processed before the while loop sets the state to 1 and sig2 to 0, which erases the evidence of SIGUSR2. To completely eliminate this race condition, the OS must queue subsequent signals while one signal is being handled, and the finite state machine must be handled by the signal handler.

...

POSIX defines the sigaction(2) function, which assigns handlers to signals like in a similar fashion to the C99 signal(2) function, but also allows one signal masks to be set explicitly set signal masks. One can thus use . Consequently, sigaction(2) and can be used to prevent a signal handler from interrupting itself.

Code Block
bgColor#ccccff
#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;
}

In fact, POSIX recommends sigaction(2) and deprecates signal(2). Unfortunately, sigaction(2) is not C99-compliantdefined in C99 and is consequently not as portable a solution.

Risk Assessment

Wiki Markup
Interrupting a non-interruptible signal handler can result in a variety of vulnerabilities  \[Zalewski 01\]
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
.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

SIG00-A

3 (high)

3 (likely)

1 (high)

P9

L2

...

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[Dowd 06 | AA. C References#Dowd 06]\] Chapter 13, "Synchronization and State" (Signal Interruption and Repetition)
\[[ISO/IEC 03|AA. C References#ISO/IEC 03]\] Section 5.2.3, "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]
\[[Dowd 06 | AA. C References#Dowd 06]\] Chapter 13, "Synchronization and State" (Signal Interruption and Repetition)

...

12. Signals (SIG)      12. Signals (SIG)       SIG01-A. Understand implementation-specific details regarding signal handler persistence