CON01-C. 同期用プリミティブの取得と解放は、同じ翻訳単位内の同一抽象レベルで行う
ミューテックスのロックとロック解除はすべて、同じ翻訳単位内の同一抽象レベルで行うべきである。このレコメンデーションに従わないと、マルチスレッドプログラムによるロックやロック解除が意図したとおりに実行されず、ミューテックスの種類によっては、最終的にデッドロック、競合状態といったセキュリティ上の脆弱性につながる可能性がある。
一般に、ミューテックスを適切にロックしないと、mtx_unlock()
が 2 回呼び出されて 2 回ロック解除される。これが原因で、ロック解除によりエラーが返されることがある。再帰的なミューテックスの場合は、ロック回数が 0 (ミューテックスを他のスレッドで利用可能)の状態で mtx_unlock()
の呼び出しが行われた場合に限りエラーが返される。
違反コード
以下に示すマルチスレッドの銀行口座システムの簡単なコードの例では、最低限必要な残高に達している口座を想定している。コードでは、引き落とし処理がすべて正当であることを確認する必要がある。account_balance
が MIN_BALANCE
を下回るような現金の引き出しを要求する debit()
の呼び出しが行われたとすると、mtx_unlock()
の呼び出しが 2 回行われる可能性がある。この例では、ミューテックスが静的に定義されているため、ミューテックスの型は処理系定義となる。
#include <threads.h> enum { MIN_BALANCE = 50 }; int account_balance; mtx_t mp; /* mp を初期化 */ int verify_balance(int amount) { if (account_balance - amount < MIN_BALANCE) { /* エラー条件の処理 */ if (mtx_unlock(&mp) == thrd_error) { /* エラー処理 */ } return -1; } return 0; } void debit(int amount) { if (mtx_lock(&mp) == thrd_error) { /* エラー処理 */ } if (verify_balance(amount) == -1) { if (mtx_unlock(&mp) == thrd_error) { /* エラー処理 */ } return; } account_balance -= amount; if (mtx_unlock(&mp) == thrd_error) { /* エラー処理 */ } }
適合コード
この適合コードは、ミューテックスのロック解除を、ロックしたときと同じ翻訳単位内の同一抽象レベルで行っている。この方法により、ミューテックスが 2 回ロック解除されないことを保証している。
#include <threads.h> enum { MIN_BALANCE = 50 }; static int account_balance; static mtx_t mp; /* mp を初期化 */ static int verify_balance(int amount) { if (account_balance - amount < MIN_BALANCE) return -1; /* 呼び出し元にエラーを返す */ return 0; } int debit(int amount) { if (mtx_lock(&mp) == thrd_error) return -1; /* 呼び出し元にエラーを返す */ if (verify_balance(amount)) { mtx_unlock(&mp); return -1; /* 呼び出し元にエラーを返す */ } account_balance -= amount; if (mtx_unlock(&mp) == thrd_error) return -1; /* 呼び出し元にエラーを返す */ return 0; /* 成功を指摘 */ }
リスク評価
ミューテックスを適切に使用しないと、サービス運用妨害(DoS)攻撃や、マルチスレッドプログラムの予期せぬ終了が引き起こされる可能性がある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
CON01-C |
低 |
中 |
中 |
P4 |
L3 |
自動検出(最新の情報はこちら)
ツール | バージョン | チェッカー | 説明 |
---|---|---|---|
Coverity | 6.5 | LOCK | 実装済み |
参考資料
[Open Group 2008] | pthread_mutex_lock()/pthread_mutex_unlock() pthread_mutex_init() , pthread_mutexattr_init() |
翻訳元
これは以下のページを翻訳したものです。
CON01-C. Acquire and release synchronization primitives in the same module, at the same level of abstraction (revision 30)