根据UNIX环境中的高级编程, openat()
提供了一种避免使用时间检查(TOCTTOU)错误的方法。
我对如何感到困惑。据我所知,openat
依赖于文件描述符,因此需要首先打开此文件描述符-这会引入TOCTTOU吗?
最佳答案
openat()
的POSIX规范说:
这意味着,如果要将文件放置在特定目录中或相对于特定目录放置,则可以打开该目录的文件描述符(可能使用O_SEARCH
选项),然后在openat()
系统调用中指定相对于该目录的路径名。
其他*at()
函数(例如 fstatat()
)也可以类似地工作。
首先,请注意文件描述符是目录的文件描述符。在打开目录(以供读取)时,该目录已存在,并且该进程有权访问该目录及其中的文件。此外,由于此进程已打开目录,因此直到该进程关闭目录文件描述符后,对该目录的最后引用才会消失。如果在已安装的文件系统上,则在程序终止之前无法卸载该文件系统(因为该进程已打开目录)。如果移动目录(在同一文件系统上),则将在文件系统中当前位置相对于该目录继续创建文件。
从此以后,事情变得更加投机了-我尚未正式测试这些观察结果。
即使目录已删除,您似乎仍然可以创建相对于该目录的文件。如果名称是简单名称(
"new_file"
或"./new_file"
),则应该可以。如果名称具有更多的路径("subdir/new_file"
),则如果目录被删除,则创建或打开文件将失败,因为所有子目录也将被删除。当然,有
mkdirat()
可以创建子目录。据推测,文件系统必须在所有这些之后清理,这可能非常复杂。这意味着实际上您有可能无法在具有打开的文件描述符但已删除其名称的目录中创建文件。但是,您将知道不再可能,而不是假定它是同一目录。
无论哪种方式,只要您在使用正确的
*at()
函数时都谨慎且一致,就很难使攻击者混淆您的程序在错误的目录中创建文件。删除了一组TOCTOU攻击;那些依赖于目录被重命名(或可能被删除)并使用新名称(例如,指向其他位置的符号链接(symbolic link))的攻击被挫败了,因为相对于原始目录继续创建文件,而不是使用重命名或替换文件目录。
openat()
的POSIX规范的基本原理部分说:关于unix - openat如何避免TOCTTOU错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36708171/