SV.INCORRECT_RESOURCE_HANDLING.URH

Insecure resource handling-allocation and release

Resource management issues can lead to over-consumption or exhaustion of resources. When a resource is allocated, it's important to release the resource properly and account for all potential exit paths. Similarly, the code needs to keep track of requests and releases, so that a resource isn't requested after it's been released. This type of defect often occurs in function exits for exceptions or error handling.

The SV.INCORRECT_RESOURCE_HANDLING.URH checker flags situations in which a resource is requested after it may have been released. The checker analyzes the following POSIX resources for incorrect resource handling:

  • Standard input/output resources: file descriptors, file, and pipe streams
  • X/Open System Interface (XSI) resources: messages, semaphores, and shared memory
  • Realtime resources: message queues, semaphores, shared memory, typed memory objects, process spawning, clocks, and timers
  • Thread resources: threads, mutexes, conditional variables, barriers, read/write lock objects, and spin lock objects
  • Sockets
  • Traces

For more information, see the latest issue of The Open Group Base Specifications.

Vulnerability and risk

Although this situation is not really a security risk, incorrect error handling can result in software reliability problems, and possibly in exposing sensitive data. If an attacker can intentionally trigger a resource leak, a resource pool could be reduced to the point of denial-of-service (DoS).

Mitigation and prevention

It's good practice to ensure that all resources allocated are subsequently freed, and to be consistent with allocation and release of resources in a function and in an application. Error conditions, in particular, should always be checked to make sure that resources are assigned and freed appropriately.

Vulnerable code example

Copy
   #include <stdio.h>
   #include <mqueue.h>
  
   void message_released(const char* name, const char* data1, const char* data2)
   {
  
         char c;
         mqd_t h;
         if ((h = mq_open(name, O_RDWR)) != (mqd_t)-1)
        {
                      mq_receive(h, &c, 1, NULL);
                      if (c == '1')
                               mq_send(h, data1, strlen(data1)+1, 2);
                      else
 
                      if (c == '2')
                               mq_send(h, data2, strlen(data2)+1, 2);
                      mq_close(h);
                      printf("OK.\n");
                      mq_send(h, "OK.", 3, 2); // ERROR
        }
        else
        {
                      fprintf(stderr, "'mq_open' failed for %s\n", name);
 
        }
  }

Klocwork produces an issue report at line 20, indicating that handler 'h', which is the result of a call to 'mq_open', was used after it was released in line 18. Incorrect resource handling like this can cause software reliability problems.

Fixed code example

Copy
   #include <stdio.h>
   #include <mqueue.h>
  
   void message_released(const char* name, const char* data1, const char* data2)
   {
  
         char c;
         mqd_t h;
         if ((h = mq_open(name, O_RDWR)) != (mqd_t)-1)
        {
                      mq_receive(h, &c, 1, NULL);
                      if (c == '1')
                               mq_send(h, data1, strlen(data1)+1, 2);
                      else
 
                      if (c == '2')
                               mq_send(h, data2, strlen(data2)+1, 2);
                      printf("OK.\n");
                      mq_send(h, "OK.", 3, 2);
                      mq_close(h);
        }
        else
        {
                      fprintf(stderr, "'mq_open' failed for %s\n", name);
 
        }
  }

In the fixed code example, handler 'h' isn't released until line 21, after the call to 'mq_send'.