Versions Compared

Key

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

Call only only asynchronous-safe functions within signal handlers. For strictly conforming programs, only the C Standard Library functions abort(), _Exit(), and signal() can be called from within a signal handler in the C Standard Libraryhandler

Section 7.14.1.1, para. 5, of the C standard [ISO/IEC 9899:2011], states that if the signal occurs other than as the result of calling the abort() or raise() function, the behavior is undefined if

...

Code Block
bgColor#FFcccc
langc
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

enum { MAXLINE = 1024 };
char *info = NULL;

void log_message(void) {
  fprintf(stderr, info); /* violation */
}

void handler(int signum) {
  log_message();
  free(info); /* violation */
  info = NULL;
}

int main(void) {
  if (signal(SIGINT, handler) == SIG_ERR) {
    /* Handle error */
  }
  info = (char*)malloc(MAXLINE);
  if (info == NULL) {
    /* Handle Error */
  }

  while (1) {
    /* Main loop program code */

    log_message();

    /* More program code */
  }
  return 0;
}

...

Code Block
bgColor#ffcccc
langc
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>

enum { MAXLINE = 1024 };
static jmp_buf env;

void handler(int signum) {
  longjmp(env, 1); /* violation */
}

void log_message(char *info1, char *info2) {
  static char *buf = NULL;
  static size_t bufsize;
  char buf0[MAXLINE];

  if (buf == NULL) {
    buf = buf0;
    bufsize = sizeof(buf0);
  }

  /*
   *  Try to fit a message into buf, else re-allocate
   *  it on the heap and then log the message.
   */

/*** VULNERABILITY IF SIGINT RAISED HERE ***/

  if (buf == buf0) {
    buf = NULL;
  }
}

int main(void) {
  if (signal(SIGINT, handler) == SIG_ERR) {
    /* Handle error */
  }
  char *info1;
  char *info2;

  /* info1 and info2 are set by user input here */

  if (setjmp(env) == 0) {
    while (1) {
      /* Main loop program code */
      log_message(info1, info2);
      /* More program code */
    }
  }
  else {
    log_message(info1, info2);
  }

  return 0;
}

...