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 行目で、'mq_open' への呼び出しの結果であるハンドラー 'h' が、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' への呼び出しの後で、ハンドラー 'h' は 21 行目まで解放されません。