8

タイトルはすべてを物語っています: Time of Check to Time of Use (TOCTOU) 競合状態を回避するためstat() に afterを使用できますか? fopen()

いくつかの詳細:

ファイルの読み取りのみを行う C プログラムを作成していますが、ディレクトリの読み取りを要求されたときに適切にエラーが発生する必要があります。現時点では、open()(with ) を使用してエラーを生成し、次のようにO_RDWRをチェックerrnoします。EISDIR

int fd = open(path, O_RDWR);

if (fd == -1) {
    if (errno == EISDIR) return PATH_IS_DIR;
    else return FILE_ERR;
}

上記の解決策の問題は、このプログラムがファイルを読み取るだけでよいことです。そのため、でファイルを開くとO_RDWR、ユーザーが読み取り権限を持っているが書き込み権限を持っていない場合、誤って権限エラーが発生する可能性があります。

TOCTOU 競合状態を回避するために次のことを行うことは可能ですか?

struct stat pstat;

FILE *f = fopen(path, "r");

if (!f) return FILE_ERR;

if (stat(path, &pstat) == -1) {
    fclose(f);
    return FILE_ERR;
}

if (S_ISDIR(pstat.st_mode)) {
    fclose(f);
    return PATH_IS_DIR;
}

それが不可能な場合、TOCTOU のバグや間違った許可エラーを防ぐ別の解決策はありますか?

4

2 に答える 2

6

編集(2018-10-25): Toby Speight の回答の方が優れています。

解決策があります: を使用しopen()、次に を 使用しfstat()ます。

例:

struct stat pstat;

int fd = open(path, O_RDONLY);

if (fd == -1) return FILE_ERR;

if (fstat(fd, &pstat) == -1) {
    close(fd);
    return FILE_ERR;
}

if (S_ISDIR(pstat.st_mode)) {
    close(fd);
    return PATH_IS_DIR;
}

この質問をする前に、すべてのベースをカバーしたことを確認しているときにこれを見つけました。

于 2018-10-23T15:26:09.960 に答える