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
#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
#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'.