SV.INCORRECT_RESOURCE_HANDLING.URH

不安全的资源处理 - 分配和释放

资源管理问题可导致过度消耗资源或耗尽资源。分配资源时,务必要正确地释放资源并且说明所有潜在的退出路径。类似的,代码需要跟踪资源的请求和释放情况,以保证不会请求已被释放的资源。此类型的漏洞通常出现在因异常或错误处理而退出函数时。

SV.INCORRECT_RESOURCE_HANDLING.URH 检查器会标记出请求可能已经被释放的资源的情况。检查器会分析以下 POSIX 资源,以查找错误的资源处理:

  • 标准输入/输出资源:文件描述符、文件以及管道流
  • X/开放式系统接口 (XSI) 资源:消息、信号灯,以及共享内存
  • 实时资源:消息队列、信号灯、共享内存、已指定类型的内存对象、进程派生、时钟以及计时器
  • 线程资源:线程、互斥、条件变量、障碍、读取/写入锁定对象以及旋转锁定对象
  • 套接字
  • 跟踪

有关详细信息,请参阅最新发布的“开放式组基本规范”。

漏洞与风险

虽然此情况并不是真正的安全性风险,但是不正确的错误处理可能导致软件可靠性问题,并且可能泄露敏感数据。如果攻击者可以蓄意地触发资源泄露,则资源库会被削减,直至导致拒绝服务 (DoS)。

缓解与预防

正确的做法是确保所有已分配的资源在随后都得到释放,并且与函数和应用程序中的资源分配与释放保持一致。特别是应始终检查错误条件,以确保适当地分配和释放资源。

漏洞代码示例

复制
   #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 针对第 20 行生成问题报告,表明处理程序 h(调用 mq_open 产生的结果)在第 18 行中被释放后使用。像这样不正确的资源处理可导致软件可靠性问题。

修正代码示例

复制
   #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);
 
        }
  }

在此修正代码示例中,调用 mq_send 之后,直至第 21 行才会释放处理程序 h。