JPCERT コーディネーションセンター

POS30-C. readlink() 関数を適切に使用する

POS30-C. readlink() 関数を適切に使用する

readlink() 関数は、第1引数に渡されたシンボリックリンクのリンク先を読み取り、第2引数が指すバッファに格納する。格納される文字列はナル終端されない。バッファに書き込んだ文字数が関数の返り値となる。

違反コード

このコード例では、lensizeof(buf) と等しい場合、buf の終端を 1 バイト越えた場所にナル文字が書き込まれてしまう。

char buf[1024];
ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf));
buf[len] = '\0';

次の修正例では、buf を十分大きくし、結果を常に保持できるようにしようとしている。

long symlink_max;
size_t bufsize;
char *buf;
ssize_t len;

errno = 0;
symlink_max = pathconf("/usr/bin/", _PC_SYMLINK_MAX);
if (symlink_max == -1) {
  if (errno != 0) {
    /* エラー処理 */
  }
  bufsize = 10000;
}
else {
  bufsize = symlink_max+1;
}

buf = (char *)malloc(bufsize);
if (buf == NULL) {
  /* エラー処理 */
}

len = readlink("/usr/bin/perl", buf, bufsize);
buf[len] = '\0';

この修正では、シンボリックリンクのリンク先の長さは、pathconf() が返す SYMLINK_MAX の値を超えることはないと想定している。しかし、これは誤りである。pathconf() が返した値は readlink() が呼び出された時点で無効になっている可能性があり、オフバイワンバッファオーバーフローのリスクは依然として存在する。その理由は、これら2つの関数の呼出しの間に /usr/bin/perl の置かれている領域が、より大きな SYMLINK_MAX 値を持つファイルシステムに移動される可能性があるからである。また、SYMLINK_MAX が不定の場合(つまり pathconf()-1 を返し errno も設定しない場合)、任意のバッファサイズ(このコード例では10,000)を十分なサイズであることを期待して使用しているが、readlink() が丁度このサイズを返す可能性がないとは言えないだろう。

また、readlink() は失敗した場合に -1 を返すので、その場合オフバイワンアンダーフローが発生する可能性がある。

適合コード

次の適合コードでは、バッファに書き込むのは sizeof(buf)-1 文字のみであるため、オーバーフローは発生しない。またエラーの発生を適切に確認している。

enum { BUFFERSIZE = 1024 };
char buf[BUFFERSIZE];
ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf)-1);

if (len != -1) {
  buf[len] = '\0';
}
else {
  /* エラー処理 */
}
リスク評価

readlink() の結果を適切にナル終端しないと、プログラムの異常終了やバッファオーバーフローにつながる可能性がある。

ルール

深刻度

可能性

修正コスト

優先度

レベル

POS30-C

P12

L1

自動検出(最新の情報はこちら

ツール

バージョン

チェッカー

説明

Compass/ROSE

 

 

 

Coverity 6.5 READLINK 実装済み
関連するガイドライン
MITRE CWE CWE-170, Improper null termination
参考文献
[Ilja 2006]
[Open Group 1997a]
[Open Group 2004]
翻訳元

これは以下のページを翻訳したものです。

POS30-C. Use the readlink() function properly (revision 60)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter