CON00-C. 複数のスレッドによる競合状態を避ける
複数のスレッドから同じデータの読み取りや変更ができる場合は、同期の手法を用いて、セキュリティ上の脆弱性につながり得るソフトウェアの欠陥を避けること。同時実行の問題が原因で異常終了やサービス運用妨害(DoS)につながることが多いが、より深刻な脆弱性が引き起こされる可能性もある。
違反コード
以下のようなマルチスレッドの銀行口座システムの一部である簡単なコードがあるとする。ある口座に対して入金と出金が行われるたびに、複数のスレッドが credit()
と debit()
を呼び出す。加算と減算はアトミックな操作ではないため、account_balance
volatile
が宣言されるにもかかわらず、2 つの操作が同時に発生する可能性があるが、保存されるのは一方の操作の結果のみである。たとえば、攻撃者は一定の金額を入金し、少額の引き落としを同時に大量に発生させることができる。競合状態が原因で、引き落としのいくつかは口座残高に影響を及ぼすことなく実行され、攻撃者は事実上、金を作り出すことになる。
static volatile int account_balance; void debit(int amount) { account_balance -= amount; } void credit(int amount) { account_balance += amount; }
適合コード (ミューテックス)
以下の適合コードは、ミューテックスを使用して入金と出金の処理をアトミックにしたものである。これにより、すべての入出金処理が預金残高に反映されるため、攻撃者は競合状態を悪用して口座から金を盗むことはできない。ミューテックスの作成は mtx_init()
関数で行う。ミューテックスの存在により account_balance
volatile
の宣言が不要になることに注意。
#include <threads.h> static int account_balance; static mtx_t account_lock; if(mtx_init(&account_lock, mtx_plain) == thrd_error) /* エラー処理 */ /* ... */ int debit(int amount) { if (mtx_lock(&account_lock) == thrd_error) return -1; /* 呼び出し元にエラーを返す */ account_balance -= amount; if (mtx_unlock(&account_lock) == thrd_error) return -1; /* 呼び出し元にエラーを返す */ return 0; /* 成功を指摘 */ } int credit(int amount) { if (mtx_lock(&account_lock) == thrd_error) return -1; /* 呼び出し元にエラーを返す */ account_balance += amount; if (mtx_unlock(&account_lock) == thrd_error) return -1; /* 呼び出し元にエラーを返す */ return 0; /* 成功を指摘 */ }
適合コード (アトミック)
以下の適合コードは、アトミック変数を使用して入金と出金の処理を同期化したものである。これにより、すべての入出金処理が預金残高に反映されるため、攻撃者は競合状態を悪用して口座から金を盗むことはできない。アトミック整数の作成は、atomic_init()
関数で行う。
#include <stdatomic.h> atomic_int account_balance; /* account_balance の初期化 */ void debit(int amount) { atomic_fetch_sub(account_balance, amount); } void credit(int amount) { atomic_fetch_add(account_balance, amount); }
リスク評価
複数のスレッドが同じデータに同時にアクセスしたり変更したりすることで生じる競合状態は、プログラムの異常終了やサービス運用妨害(DoS)攻撃、あるいはデータ完全性の侵害につながるおそれがある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
CON00-C |
中 |
中 |
高 |
P4 |
L3 |
自動検出(最新の情報はこちら)
ツール | バージョン | チェッカー | 説明 |
---|---|---|---|
Coverity | 6.5 | MISSING_LOCK | 実装済み |
関連するガイドライン
MITRE CWE | CWE-366, Race condition within a thread |
参考資料
[Dowd 2006] | Chapter 13, "Synchronization and State" |
[Plum 2012] | |
[Seacord 2013] | Chapter 8, "File I/O" |
翻訳元
これは以下のページを翻訳したものです。
CON00-C. Avoid race conditions with multiple threads (revision 68)