CERT.SIG.SIG_HANDLER.SHARED_OBJ.HEAP

Do not access shared object in signal handlers

This checker is applicable only to the modern engine.

The checker CERT.SIG.SIG_HANDLER.SHARED_OBJ.HEAP looks for for any heap access in signal handlers.

This checker triggers when a signal handler allocates or deallocates data on the heap, including the use of:

  • C++ operators
    • new
    • delete
  • C functions
    • malloc
    • calloc
    • realloc
    • free
  • Allocator functions
    • std::allocator::allocate

    • std::allocator::deallocate

Vulnerability and risk

Accessing or modifying shared objects in signal handlers can result in race conditions that can leave data in an inconsistent state. The two exceptions (C Standard, 5.1.2.3, paragraph 5) to this rule are the ability to read from and write to lock-free atomic objects and variables of type volatile sig_atomic_t. Accessing any other type of object from a signal handler is undefined behavior.

Mitigation and prevention

Do not access or allocate to the heap in signal handlers.

Vulnerable code example

Copy
#include <signal.h>
#include <stdlib.h>
#include <string.h>

enum { MAX_MSG_SIZE = 24 };
char *err_msg;

void handler(int signum) {
  char* err_msg_copy = (char *)malloc(MAX_MSG_SIZE);
}

int main(void) {
  signal(SIGINT, handler);

  err_msg = (char *)malloc(MAX_MSG_SIZE);
  if (err_msg == NULL) {
    /* Handle error */
  }
  strcpy(err_msg, "No errors yet.");
  /* Main code loop */
  return 0;
}

The code is non-compliant as there is a call to malloc in the signal handler.

Fixed code example

Copy
#include <signal.h>
#include <stdlib.h>
#include <string.h>

enum { MAX_MSG_SIZE = 24 };
char *err_msg;

void handler(int signum) {
  char err_msg_copy[MAX_MSG_SIZE];
}

int main(void) {
  signal(SIGINT, handler);

  err_msg = (char *)malloc(MAX_MSG_SIZE);
  if (err_msg == NULL) {
    /* Handle error */
  }
  strcpy(err_msg, "No errors yet.");
  /* Main code loop */
  return 0;
}

The code is now compliant as we do not allocate memory on the heap but allocate memory on the stack.