Gav*_*ard 5 c fopen posix stat fstat
标题说明了一切:可以使用stat() 之后 fopen()避免使用时间(TOCTOU)竞争条件吗?
一些细节:
我正在编写一个只读取文件的C程序,但在被要求读取目录时需要正确错误.截至目前,它使用open()(与O_RDWR),以产生一个错误,然后检查errno为EISDIR,像这样:
int fd = open(path, O_RDWR);
if (fd == -1) {
if (errno == EISDIR) return PATH_IS_DIR;
else return FILE_ERR;
}
Run Code Online (Sandbox Code Playgroud)
上述解决方案的问题是该程序只需要读取文件,因此通过打开文件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;
}
Run Code Online (Sandbox Code Playgroud)
如果不可能,是否有其他解决方案可以防止TOCTOU错误以及错误的权限错误?
编辑(2018-10-25):Toby Speight的答案更好.
一个例子:
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;
}
Run Code Online (Sandbox Code Playgroud)
在问这个问题之前,我在检查我已经覆盖了所有基地时找到了这个.
不,问题中出现的代码不能避免参加TOCTOU竞赛。
使用后进行测试时,容易发生与使用前测试完全相同的错误。在这两种情况下,名称都在两个不同的时间解析,结果可能不同。这是比赛的原因,无论哪种访问先发生,它都可能发生。
避免这种情况的唯一方法是一次打开文件,然后将如此获得的文件描述符用于所需的任何其他检查。现代OS fstat()为此提供了诸如此类的接口。
如果要使用C的缓冲I / O,则可以FILE*使用fileno()- 获得文件描述符,也可以使用使用- FILE*从文件描述符创建文件描述符fdopen()。
它需要对您的代码进行很小的更改:
# Untested
struct stat pstat;
FILE *f = fopen(path, "r");
if (!f) return FILE_ERR;
if (fstat(fileno(f), &pstat) == -1) {
// ^^^^^^^^^^^^^^^ <-- CHANGED HERE
fclose(f);
return FILE_ERR;
}
if (S_ISDIR(pstat.st_mode)) {
fclose(f);
return PATH_IS_DIR;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
427 次 |
| 最近记录: |