POS48-C. 他の POSIX スレッドのミューテックスをアンロックしたり破壊したりしない
ミューテックスは、同時にアクセスされる共有データ構造を保護するために使用される。ミューテックスをロックするスレッドがミューテックスを所有し、唯一このスレッドがミューテックスをアンロックできるスレッドでなければならない。ミューテックスがまだ使用されている間に破棄された場合、クリティカルセクションや共有データは保護されなくなる。このガイドラインは「CON31-C. 他のスレッドのミューテックスをアンロックしたり破壊したりしない」の POSIX スレッドを使用した場合の例である。
違反コード
次の違反コード例では、クリーンアップスレッドと作業スレッドの間に競合状態が存在する。クリーンアップスレッドは、ロックはすでに使われていないものと想定して(即座に)ロックを破棄する。システムで負荷のかかる処理を行っている場合、ロックを保持していた作業スレッドは、予想よりも長く処理に時間がかかる可能性がある。作業スレッドが共有データを変更し終える前にロックが破棄されると、プログラムは予期せぬ動作を引き起こすかもしれない。
pthread_mutex_t theLock;
int data;
int cleanupAndFinish(void) {
int result;
if ((result = pthread_mutex_destroy(&theLock)) != 0) {
/* エラー処理 */
}
data++;
return data;
}
void worker(int value) {
if ((result = pthread_mutex_lock(&theLock)) != 0) {
/* エラー処理 */
}
data += value;
if ((result = pthread_mutex_unlock(&theLock)) != 0) {
/* エラー処理 */
}
}
適合コード
次の適合コードでは、ミューテックスが不要になるまで待ってからミューテックスを破棄している。また、ミューテックスをロックするときはエラー条件をチェックすることが重要である。
mutex_t theLock;
int data;
int cleanupAndFinish(void) {
int result;
/* アプリケーションによって異なるユーザ定義の関数 */
wait_for_all_threads_to_finish();
if ((result = pthread_mutex_destroy(&theLock)) != 0) {
/* エラー処理 */
}
data++;
return data;
}
void worker(int value) {
int result;
if ((result = pthread_mutex_lock(&theLock)) != 0) {
/* エラー処理 */
}
data += value;
if ((result = pthread_mutex_unlock(&theLock)) != 0) {
/* エラー処理 */
}
}
リスク評価
ミューテックスの所有権を無視することのリスクは、ミューテックスを全く使用しないリスクと同等であり、データ完全性が損われる可能性がある。
ルール |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
POS48-C |
中 |
中 |
高 |
P4 |
L3 |
自動検出(最新の情報はこちら)
Tool |
Version |
Checker |
Description |
---|---|---|---|
Fortify SCA | V. 5.0 | CERT C Rule Packを使ってこのルールの違反を検出できる |
関連するガイドライン
MITRE CWE | CWE-667, Insufficient locking |
参考資料
[Open Group 2004] | pthread_mutex_lock()/pthread_mutex_unlock() pthread_mutex_destroy() |
翻訳元
これは以下のページを翻訳したものです。
POS48-C. Do not unlock or destroy another POSIX thread's mutex (revision 6)