You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

A signal handler should not re-assert its desire to handle its own signal. This is often done on non-persistent platforms, that is, when a signal handler receives a signal that is bound to a handler, they unbind the signal to default behavior before calling the handler.

A signal handler may call signal() to reset the signal, or change the current way signals are handled.

Non-Compliant Code Example

In this non-compliant code example, the signal handler handler() is bound to signum.

void handler(int signum) {
  signal(signum, handler);
  /* handling code */
}
/* ... */
signal(signum, handler);

Unfortunately this solution contains a race window, starting when the host environment resets the signal and ending when the handler calls signal(). During that time, a second signal sent to the program will trigger the default signal behavior, thereby defeating the persistent behavior implied by the call to signal() from within the handler to reassert the binding.

If the environment is persistent (that is, it does not reset the handler when the signal is received), the handler's signal() function is redundant.

Compliant Solution

For persistent platforms, the handler's signal() function is unnecessary.

void handler(int signum) {
  /* handling code */
}
/* ... */
signal(signum, handler);

Compliant Solution (POSIX)

POSIX defines the sigaction(2) function, which assigns handlers to signals like signal(2), but also allows one to explicitly set persistence. One can thus use sigaction(2) and sidestep the race window on non-persistent OS's.

void handler(int signum) {
  /* handling code */
}
/* ... */
/* Equivalent to signal( signum, handler);
   but make signal persistent */
struct sigaction act;
act.sa_handler = &handler;
act.sa_flags = 0;
if (sigemptyset( &act.sa_mask) != 0) {
  /* handle error */
}
if (sigaction(signum, &act, NULL) != 0) {
  /* handle error */
}

In fact, POSIX recommends sigaction(2) and deprecates signal(2). Unfortunately, sigaction(2) is not C99-compliant, and is not supported on some platforms, including Windows.

Risk Assessment

Two signals in quick succession can trigger the race condition on non-persistent platforms, thereby causing the signal's default behavior despite a handler's attempt to override it.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

SIG34-C

1 (low)

1 (unlikely)

3 (low)

P3

L3

Related Vulnerabilities

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

References

[[ISO/IEC 9899-1999TR2]] Section 7.14.1.1, "The signal function"


SIG33-C. Do not recursively invoke the raise() function      12. Signals (SIG)       13. Error Handling with errno (ERR)

  • No labels